You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Inability to use typeof on an ES private propertyΒ #47595
The example is kept short for reproduction, but in practice this is more for cases where you would want to use keyof this.#someProperty and similar constructs (since here the type could just be inferred).
π Actual behavior
Specifying a type using const name: typeof this.#anESprivateProperty is not possible.
For p, the error is that an identifier is expected (because it's a PrivateIdentifier and not an Identifier from the compiler's pov?).
For p2, the error is that the property does not exist on the type, which is logical when done from "outside" the class where the property should not be visible.
π Expected behavior
Having the ability to use typeof on an ES private property from "inside" the class itself where that property is visible, e.g. like in the example code above.
obj['#privateProp'] accesses a different property at runtime than obj.#privateProp; the syntax in question refers to the former. That's what's meant by "already taken".
Oleksandr Tarasiuk (@a-tarasyuk) Since C["#a"] in your example already refers to the public property ("number is not assignable to string"); changing it to refer to the private property would be a pretty big breaking change.
For now I would not support indexed access lookup (const p: C["#p"] or variants thereof); it's very messy. Accessing the type of a private property from outside the class is a huge code smell since it breaks under declaration emit, and should really be avoided.
typeof this.#p (from inside the class) should be the only way to get at it.
Reacted by Oleksandr Tarasiuk, Isaiah Thomason, Kangjun Lee, Matt Kantor, Daniel Rosenwasser and Michael Tichopad
Reacted by Oleksandr Tarasiuk, Raziel and Isaiah Thomason
I posted this on #48640, but reposting here as well:
I think a better approach would have been to allow #name in an indexed access type, rather than in a type query, i.e.:
classC{
#x: Foo;private_x: Foo;method(){constp1: this[#x]=this.#x;constp2: this["_x"]=this._x;constobj=this;constp3: typeofobj[#x]=this.#x;// parsed as `(typeof obj)[#x]`constp4: typeofobj["_x"]=this._x;// parsed as `(typeof obj)["_x"]`}}
This would mean adding a PrivateNameTypeNode and we could then avoid changing TypeQueryNode or QualifiedName in any way. I would also expect that #x in a type is only legal inside of the class body, just like how a runtime private name is scoped.
If you need to access the type of a private named class member outside of the class, you would need to introduce a type alias or interface for it. If a class makes a private-named index access type public, our declaration emit would also need to synthesize a type for it outside of the class. This means that the type import("foo").Bar[#baz] would only be legal inside of a class body that declares #baz.
And that's if we decide to go that far. Given Ryan Cavanaugh (@RyanCavanaugh)'s reticence, we might decide it's not worth the complexity it would add.
I think that while supporting typeof this.#p as suggested by Ryan Cavanaugh (@RyanCavanaugh) would be great, I don't think it covers the (IMO valid) use case of static private elements accessed within non-static methods. Consider the following example:
classC{static #staticProperty ='foo';m(){consts=C.#staticProperty;// allowed in JStypeS=typeofC.#staticProperty;// makes sense in TS, but causes error}}
If one can only access private elements using typeof this.#p references, it would never be possible to use typeof for static private elements in non-static methods, right?
Activity
rraziel commentedon Jan 25, 2022
I wouldn't mind giving it a shot with a PR, but just to see if I'm at least on the right track before I start going down that path:
NodeFactory.createTypeQueryNode(when doingtypeof this.#abc) needs an entity nameNodeFactory.createQualifiedNamecan't be used for that as the second arg must be anIdentifier, and here it's aPrivateIdentifierWould this be the correct way to get the feature to work?
a-tarasyuk commentedon Jan 26, 2022
Ryan Cavanaugh (@RyanCavanaugh) Do we need to support this syntax?
TypeScript/tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts
Lines 12 to 13 in 3206df8
#aand['#a']are two different props - PlaygroundIf we allow
C["#a"], the next property should get typenumber. :)TypeScript/tests/cases/conformance/classes/members/privateNames/privateNameAndIndexSignature.ts
Line 10 in eb3e7bd
fatcerberus commentedon Jan 26, 2022
obj['#privateProp']accesses a different property at runtime thanobj.#privateProp; the syntax in question refers to the former. That's what's meant by "already taken".dnalborczyk commentedon Jan 26, 2022
already in use with public properties.
https://www.typescriptlang.org/play?#code/MYGwhgzhAECiAeYC2AHEBTaBvAsAKGmgGIUAnASwDcwAXdABVIHsVoBeaAcgAt0QQmnANz58hANqcSAVwBGIcsEYtOAXQBc0AHbSks9KXwBfUXhoBPFJmWsOCZGnSSZ8xTbVA
fatcerberus commentedon Jan 30, 2022
Oleksandr Tarasiuk (@a-tarasyuk) Since
C["#a"]in your example already refers to the public property ("numberis not assignable tostring"); changing it to refer to the private property would be a pretty big breaking change.RyanCavanaugh commentedon Feb 1, 2022
For now I would not support indexed access lookup (
const p: C["#p"]or variants thereof); it's very messy. Accessing the type of a private property from outside the class is a huge code smell since it breaks under declaration emit, and should really be avoided.typeof this.#p(from inside the class) should be the only way to get at it.dnalborczyk commentedon Feb 1, 2022
that would make sense and that's pretty much the same how
symbols as propertiesare being handled.rbuckton commentedon May 4, 2022
I posted this on #48640, but reposting here as well:
And that's if we decide to go that far. Given Ryan Cavanaugh (@RyanCavanaugh)'s reticence, we might decide it's not worth the complexity it would add.
jakebailey commentedon May 4, 2022
I've now reverted #47696 in #48959, reopening this issue.
feat(typescript): allow private properties in typeof in types
grundb commentedon Dec 19, 2025
I think that while supporting
typeof this.#pas suggested by Ryan Cavanaugh (@RyanCavanaugh) would be great, I don't think it covers the (IMO valid) use case of static private elements accessed within non-static methods. Consider the following example:If one can only access private elements using
typeof this.#preferences, it would never be possible to usetypeoffor static private elements in non-static methods, right?