@@ -23917,6 +23917,9 @@ namespace ts {
2391723917 case SyntaxKind.InstanceOfKeyword:
2391823918 return narrowTypeByInstanceof(type, expr, assumeTrue);
2391923919 case SyntaxKind.InKeyword:
23920+ if (isPrivateIdentifier(expr.left)) {
23921+ return narrowTypeByPrivateIdentifierInInExpression(type, expr, assumeTrue);
23922+ }
2392023923 const target = getReferenceCandidate(expr.right);
2392123924 const leftType = getTypeOfNode(expr.left);
2392223925 if (leftType.flags & TypeFlags.StringLiteral) {
@@ -23947,6 +23950,24 @@ namespace ts {
2394723950 return type;
2394823951 }
2394923952
23953+ function narrowTypeByPrivateIdentifierInInExpression(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
23954+ const target = getReferenceCandidate(expr.right);
23955+ if (!isMatchingReference(reference, target)) {
23956+ return type;
23957+ }
23958+
23959+ Debug.assertNode(expr.left, isPrivateIdentifier);
23960+ const symbol = getSymbolForPrivateIdentifierExpression(expr.left);
23961+ if (symbol === undefined) {
23962+ return type;
23963+ }
23964+ const classSymbol = symbol.parent!;
23965+ const targetType = hasStaticModifier(Debug.checkDefined(symbol.valueDeclaration, "should always have a declaration"))
23966+ ? getTypeOfSymbol(classSymbol) as InterfaceType
23967+ : getDeclaredTypeOfSymbol(classSymbol);
23968+ return getNarrowedType(type, targetType, assumeTrue, isTypeDerivedFrom);
23969+ }
23970+
2395023971 function narrowTypeByOptionalChainContainment(type: Type, operator: SyntaxKind, value: Expression, assumeTrue: boolean): Type {
2395123972 // We are in a branch of obj?.foo === value (or any one of the other equality operators). We narrow obj as follows:
2395223973 // When operator is === and type of value excludes undefined, null and undefined is removed from type of obj in true branch.
@@ -27790,6 +27811,40 @@ namespace ts {
2779027811 }
2779127812 }
2779227813
27814+ function checkGrammarPrivateIdentifierExpression(privId: PrivateIdentifier): boolean {
27815+ if (!getContainingClass(privId)) {
27816+ return grammarErrorOnNode(privId, Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies);
27817+ }
27818+ if (!isExpressionNode(privId)) {
27819+ return grammarErrorOnNode(privId, Diagnostics.Private_identifiers_are_only_allowed_in_class_bodies_and_may_only_be_used_as_part_of_a_class_member_declaration_property_access_or_on_the_left_hand_side_of_an_in_expression);
27820+ }
27821+ if (!getSymbolForPrivateIdentifierExpression(privId)) {
27822+ return grammarErrorOnNode(privId, Diagnostics.Cannot_find_name_0, idText(privId));
27823+ }
27824+ return false;
27825+ }
27826+
27827+ function checkPrivateIdentifierExpression(privId: PrivateIdentifier): Type {
27828+ checkGrammarPrivateIdentifierExpression(privId);
27829+ const symbol = getSymbolForPrivateIdentifierExpression(privId);
27830+ if (symbol) {
27831+ markPropertyAsReferenced(symbol, /* nodeForCheckWriteOnly: */ undefined, /* isThisAccess: */ false);
27832+ }
27833+ return anyType;
27834+ }
27835+
27836+ function getSymbolForPrivateIdentifierExpression(privId: PrivateIdentifier): Symbol | undefined {
27837+ if (!isExpressionNode(privId)) {
27838+ return undefined;
27839+ }
27840+
27841+ const links = getNodeLinks(privId);
27842+ if (links.resolvedSymbol === undefined) {
27843+ links.resolvedSymbol = lookupSymbolForPrivateIdentifierDeclaration(privId.escapedText, privId);
27844+ }
27845+ return links.resolvedSymbol;
27846+ }
27847+
2779327848 function getPrivateIdentifierPropertyOfType(leftType: Type, lexicallyScopedIdentifier: Symbol): Symbol | undefined {
2779427849 return getPropertyOfType(leftType, lexicallyScopedIdentifier.escapedName);
2779527850 }
@@ -32110,11 +32165,29 @@ namespace ts {
3211032165 if (leftType === silentNeverType || rightType === silentNeverType) {
3211132166 return silentNeverType;
3211232167 }
32113- leftType = checkNonNullType(leftType, left);
32168+ if (isPrivateIdentifier(left)) {
32169+ if (languageVersion < ScriptTarget.ESNext) {
32170+ checkExternalEmitHelpers(left, ExternalEmitHelpers.ClassPrivateFieldIn);
32171+ }
32172+ // Unlike in 'checkPrivateIdentifierExpression' we now have access to the RHS type
32173+ // which provides us with the opportunity to emit more detailed errors
32174+ if (!getNodeLinks(left).resolvedSymbol && getContainingClass(left)) {
32175+ const isUncheckedJS = isUncheckedJSSuggestion(left, rightType.symbol, /*excludeClasses*/ true);
32176+ reportNonexistentProperty(left, rightType, isUncheckedJS);
32177+ }
32178+ }
32179+ else {
32180+ leftType = checkNonNullType(leftType, left);
32181+ // TypeScript 1.0 spec (April 2014): 4.15.5
32182+ // Require the left operand to be of type Any, the String primitive type, or the Number primitive type.
32183+ if (!(allTypesAssignableToKind(leftType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbolLike) ||
32184+ isTypeAssignableToKind(leftType, TypeFlags.Index | TypeFlags.TemplateLiteral | TypeFlags.StringMapping | TypeFlags.TypeParameter))) {
32185+ error(left, Diagnostics.The_left_hand_side_of_an_in_expression_must_be_a_private_identifier_or_of_type_any_string_number_or_symbol);
32186+ }
32187+ }
3211432188 rightType = checkNonNullType(rightType, right);
3211532189 // TypeScript 1.0 spec (April 2014): 4.15.5
32116- // The in operator requires the left operand to be of type Any, the String primitive type, or the Number primitive type,
32117- // and the right operand to be
32190+ // The in operator requires the right operand to be
3211832191 //
3211932192 // 1. assignable to the non-primitive type,
3212032193 // 2. an unconstrained type parameter,
@@ -32132,10 +32205,6 @@ namespace ts {
3213232205 // unless *all* instantiations would result in an error.
3213332206 //
3213432207 // The result is always of the Boolean primitive type.
32135- if (!(allTypesAssignableToKind(leftType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbolLike) ||
32136- isTypeAssignableToKind(leftType, TypeFlags.Index | TypeFlags.TemplateLiteral | TypeFlags.StringMapping | TypeFlags.TypeParameter))) {
32137- error(left, Diagnostics.The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol);
32138- }
3213932208 const rightTypeConstraint = getConstraintOfType(rightType);
3214032209 if (!allTypesAssignableToKind(rightType, TypeFlags.NonPrimitive | TypeFlags.InstantiableNonPrimitive) ||
3214132210 rightTypeConstraint && (
@@ -33517,6 +33586,8 @@ namespace ts {
3351733586 switch (kind) {
3351833587 case SyntaxKind.Identifier:
3351933588 return checkIdentifier(node as Identifier, checkMode);
33589+ case SyntaxKind.PrivateIdentifier:
33590+ return checkPrivateIdentifierExpression(node as PrivateIdentifier);
3352033591 case SyntaxKind.ThisKeyword:
3352133592 return checkThisExpression(node);
3352233593 case SyntaxKind.SuperKeyword:
@@ -40296,6 +40367,9 @@ namespace ts {
4029640367 }
4029740368 return result;
4029840369 }
40370+ else if (isPrivateIdentifier(name)) {
40371+ return getSymbolForPrivateIdentifierExpression(name);
40372+ }
4029940373 else if (name.kind === SyntaxKind.PropertyAccessExpression || name.kind === SyntaxKind.QualifiedName) {
4030040374 const links = getNodeLinks(name);
4030140375 if (links.resolvedSymbol) {
@@ -41712,6 +41786,7 @@ namespace ts {
4171241786 case ExternalEmitHelpers.MakeTemplateObject: return "__makeTemplateObject";
4171341787 case ExternalEmitHelpers.ClassPrivateFieldGet: return "__classPrivateFieldGet";
4171441788 case ExternalEmitHelpers.ClassPrivateFieldSet: return "__classPrivateFieldSet";
41789+ case ExternalEmitHelpers.ClassPrivateFieldIn: return "__classPrivateFieldIn";
4171541790 case ExternalEmitHelpers.CreateBinding: return "__createBinding";
4171641791 default: return Debug.fail("Unrecognized helper");
4171741792 }
0 commit comments