Skip to content

Private fields in class declaration expose internal identifier in declarationsΒ #56145

Closed as not planned
@dragomirtitian

Description

@dragomirtitian

πŸ”Ž Search Terms

class expressions private fields declaration

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried

⏯ Playground Link

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:

  1. 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)
  2. Remove the private fields and lose the nominal nature of the class
  3. 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 
}

Playground Link

(It is even worse in a language service, as the id changes each time you make a change anywhere in the file)

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions