Search code examples
typescriptcompilationprivate

Compiling private to #property


Why does TSC not compile even with "target:ESnext" private class properties in #property?

Or maybe it will be done in the future?

The es2023 configuration gives an error, for ES2022 it is also not compiled into #property.


Solution

  • See microsoft/TypeScript#31670 for an authoritative answer to this question.


    If TypeScript were to emit a TypeScript private class property as a JavaScript private class member starting with #, it would unfortunately be violating one of its language design goals. TypeScript Non-Goal #5 is:

    Add or rely on run-time type information in programs, or emit different code based on the results of the type system (emphasis added). Instead, encourage programming patterns that do not require run-time metadata.

    The problem is not the declaration site of the field, but in uses of the field. TypeScript private properties are only declared as private but they are referred to with just their name:

    class Foo {
        a = 1;
        private b = 2; // declaration
        method() {
            console.log(this.a + this.b); // use
        }
    }
    

    Note that this.a and this.b are of the same form, and are emitted to JavaScript without alteration:

    /* class Foo {
        a = 1;
        b = 2; // declaration
        method() {
            console.log(this.a + this.b); // use
        }
    } */
    

    On the other hand, when you use a JavaScript private property, all references to it need to have the # sigil:

    class Foo {
        a = 1;
        #b = 2; // declaration
        method() {
            console.log(this.a + this.#b) // use
        }    
    }
    

    It would be easy enough to have the keyword private emit as # for the declaration, but in order for the compiler to know that it should emit this.a + this.#b instead of this.a + this.b, it would have to be able to use TypeScript type system information to decide. And that's against the rules.


    So it doesn't happen now, and will almost certainly never happen; if someone were to file a feature request for it, such a request would be declined. As it says in a comment on microsoft/TypeScript#31670 by the development lead of Microsoft's TypeScript team:

    Oh the other interpretation of [this suggestion] would be "Would TS emit private as #", the answer to which is definitely "no" because that would require type-directed emit.

    Playground link to code