microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
100.04k stars 12.37k forks source link

Static property access fails in transpiled JS code when referenced in a private method in TypeScript 5.2.2 #56292

Open treblasft opened 10 months ago

treblasft commented 10 months ago

šŸ”Ž Search Terms

static property access private method transpiled JS

šŸ•— Version & Regression Information

āÆ Playground Link

https://www.typescriptlang.org/play?target=9&moduleResolution=99&module=100&ts=5.2.2&noUnusedLocals=true&jsx=4&pretty=true&preserveWatchOutput=false&noErrorTruncation=true&isolatedModules=true&verbatimModuleSyntax=true&inlineSourceMap=true#code/KYDwDg9gTgLgBAYwDYEMDOa4EE4G8BQccaMKMAlgnGFBGDgLxwDkAdigLbDMDchxpClRp0AQnCZYAdCPp8iAegVEVqtXAB6WrXAAqATzDAAolFpQAXHADCKVqwjwowFABNqtI7HLBMEAGZwAK6srsD+5KzA7gAUzm6RAOYssljMAJT4-EpwALIoANZJcDAAFuSYXGUQ7mBBAEZIlHAchb4lUHZoYORI0XAAUgDKiDXAcADu0AVw6HCgRggw0fwAxEFgrmTAAKpowFAx6Xj8RM4wQVCs2DKeWPJwAL74z0A

šŸ’» Code

After updating to TypeScript 5.2.2, I encountered a TypeError when trying to access a static property on the same class. The compiled JavaScript code results in a reference to an uninitialized variable. This error seems to occur when a static member is referenced in a private method in the class.

export class A {
    static propA = 'name';
    static propB = A.propA;
    //               ^^^^^ (At runtime) TypeError: Cannot read properties of undefined (reading 'propA')

    // Making this method public makes transpiled JavaScript code work as expected
    #updateUser() {
        return A.propA;
    }
}

šŸ™ Actual behavior

The transpiled JavaScript results in a TypeError due to _a being used before it is assigned a value. The transpilation output incorrectly references _a instead of A in the static property initialization and inside the private method.

var _a;
export class A {
    static propA = 'name';
    static propB = _a.propA;
    //                ^^^^^ TypeError: Cannot read properties of undefined (reading 'propA')

    #updateUser() {
        return _a.propA; // The culprit seems to be this line
    }
}
_a = A; // _a is defined too late

šŸ™‚ Expected behavior

The static properties should be accessed the same way it does in the TypeScript code, as it is completely correct JavaScript code.

export class A {
    static propA = 'name';
    static propB = A.propA; // The static member is referenced as expected

    #updateUser() {
        return A.propA;
    }
}

Additional information about the issue

Making the #updateUser method public makes TypeScript transpile JavaScript code as expected.

jcalz commented 10 months ago

It's not a crash if it successfully emits JavaScript. "Crash" means that tsc crashes. (I wish the issue template would make this more clear)

treblasft commented 10 months ago

Thanks for the clarification, @jcalz. Updated the issue description!

savitakatwe commented 10 months ago

@treblasft `class A { static propA = 'name'; static propB: string;

constructor(){ A.propB = A.propA }

// Making this method public makes transpiled JS code work as expected updateUser() { return A.propA; } }` you might consider initializing static propB within the constructor after the class declaration.

trusktr commented 8 months ago

consider initializing static propB within the constructor after the class declaration.

Another workaround is to use this instead of A and then you also get inheritance:

export class A {
  static propA = 'name';
  static propB = this.propA;

  // Making this method public makes transpiled JS code work as expected
  #updateUser() {
    return A.propA; // also consider using `this.constructor.propA` for inheritance, but it needs casting until https://github.com/microsoft/TypeScript/issues/3841 is fixed
  }
}