Description
π Search Terms
class expressions private fields declaration
π Version & Regression Information
- This is the behavior in every version I tried
β― Playground Link
π» Code
const x = class {
#id = 10 // "__#3455@#id": number; in declarations
}
π Actual behavior
The class expression is rendered in declarations as declare const x: { new (): { "__#34@#id": number; }; }
exposing the internal identifier of the private field.
π Expected behavior
Since we can't emit #private
in an object type (like for class declarations) and we don't have class types, it's hard to come up with a solution that preserves the nominal nature of the type. I see 3 possible solutions:
- Remove the type from the field (at least the internally used type will not end up being exposed)
declare const x: { new (): { "__#34@#id": unknown ; }; }
(partial fix) - Remove the private fields and lose the nominal nature of the class
- Remove the private fields and add a unique symbol that ensures the class behaves nominally (mostly)
declare const x_private: unique symbol;
declare const x: {
new (): {
[x_private]: "#private"
};
};
Third option would be the ideal one IMO. There is precedent for adding 'fake' declarations in declaration emit (_default
for default exports, Name_Base
for classes that use expressions in the heritage clause)
Additional information about the issue
The numeric id is not stable, and can change based on what other private fields are seen before the one emitted in the declaration
class C { #x = 1 } // Comment out this line id is different
export const x = class {
#id = 10 // "__#3455@#id": number; in declarations
}
(It is even worse in a language service, as the id changes each time you make a change anywhere in the file)