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
List of keywords you searched for before creating this issue. Write them down here so that others can find this suggestion more easily and help provide feedback.
✅ Viability Checklist
My suggestion meets these guidelines:
This wouldn't be a breaking change in existing TypeScript/JavaScript code
This wouldn't change the runtime behavior of existing JavaScript code
This could be implemented without emitting different JS based on the types of the expressions
This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
Add new 'PrivateIdentifierInInExpression' expression
'prop' in obj is a BinaryExpression, but this isn't because syntactically the left side can only be a PrivateIdentifier
suggestions for alternative names instead of 'PrivateIdentifierInInExpression' ?
Error when the PrivateIdentifier can't be looked-up symbolically
outside of a class
no containing class with matching private field
Expression returns boolean
RHS must be object or any (and not null in strictNullChecks)
i.e. same rules as 'prop' in obj
Helpful error messages
Use in flowNodes and type narrowing
language server hints
suggest completion for #${privateFields} in on typing #
emit ESNext
emit down-level
add static private methods/fields support
Type Narrowing
classMyClass{
#branded =true;prop=Math.random();equals(x: unknown){if(typeofx==='object'&& #branded inx){returnx.prop===this.prop;// ^ - should we narrow 'x' to 'MyClass' here?}returnfalse;}}
Pragmatically #branded in x could narrow right down from object to MyClass as in most cases the only way x could have the privateField is by being an instance of the class. Unlike 'prop' in x where there can easily be other classes that also have a 'prop' field. So this feels like it would be a nice optimisation for the developer experience.
However this check can also be made to pass in slightly more esoteric code where x is not an instance of MyClass:
classSuperReturn{constructor(x: any){returnx;}}classMyClassextendsSuperReturn{
#branded =true;constructor(x: unknown){super(x);}staticgetBranded(x: MyClass){returnx.#branded;}}consta={};newMyClass(a);// 'a' will now have the #branded private fieldassertTrue(MyClass.getBranded(aasany));// but is not an instance of the classassertFalse(ainstanceOfMyClass);
Do we want the type narrow to go for the (assumed) common case or for the correct case? Or maybe there is a middle ground e.g. only narrow when the classes does not extend another class (I believe this is the only way the check can be 'corrupted')
Looking at instanceOf klass checks, these will narrow to klass, even though they can also be fooled by manually setting the proptype of an object. So seems like there is good precedence here already to 'do the pragmatic thing' instead of the 'correct' thing.
Currently configuration target=ES2021 means transpiling to WeakMap and target=ESNext leaves code unchanged. Will it stay this way or will ES2021 containt native private fileds or will ES2022 has been added?
Is there a table in the documentation that maps the target profile to transpilation scenarry?
Whether the title of this issue needs to be updated?
Activity
acutmore commentedon Feb 10, 2021
Good news! A few of us at Bloomberg (@bloomberg) have started discussing working on this as a TS contribution
cc: Titian Cernicova-Dragomir (@dragomirtitian) Rob Palmer (@robpalme)
acutmore commentedon Feb 20, 2021
Work has now started on this and is going well (basic parsing with simple errors and type checking).
'prop' in objis a BinaryExpression, but this isn't because syntactically the left side can only be aPrivateIdentifierPrivateIdentifiercan't be looked-up symbolicallyboolean'prop' in obj#${privateFields} inon typing#Type Narrowing
Pragmatically
#branded in xcould narrow right down fromobjecttoMyClassas in most cases the only wayxcould have the privateField is by being an instance of the class. Unlike'prop' in xwhere there can easily be other classes that also have a'prop'field. So this feels like it would be a nice optimisation for the developer experience.However this check can also be made to pass in slightly more esoteric code where
xis not an instance ofMyClass:Do we want the type narrow to go for the (assumed) common case or for the correct case? Or maybe there is a middle ground e.g. only narrow when the classes does not extend another class (I believe this is the only way the check can be 'corrupted')
Looking at
instanceOf klasschecks, these will narrow toklass, even though they can also be fooled by manually setting the proptype of an object. So seems like there is good precedence here already to 'do the pragmatic thing' instead of the 'correct' thing.sosoba commentedon Aug 4, 2021
This feature has been marked by TC39 as finished.
I have such questions.
target=ES2021means transpiling toWeakMapandtarget=ESNextleaves code unchanged. Will it stay this way or willES2021containt native private fileds or will ES2022 has been added?targetprofile to transpilation scenarry?Best regards.
acutmore commentedon Aug 4, 2021
ES2021 was finalised before this proposal went to stage 4 so it will be part of ES2022