diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5aea2c15d4f21..92bc88664b6d0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -945,6 +945,8 @@ import { PredicateSemantics, PrefixUnaryExpression, PrivateIdentifier, + PrivateNameType, + PrivateNameTypeNode, Program, PromiseOrAwaitableType, PropertyAccessChain, @@ -2042,6 +2044,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { var evolvingArrayTypes: EvolvingArrayType[] = []; var undefinedProperties: SymbolTable = new Map(); var markerTypes = new Set(); + var privateNameTypes = new Map(); var unknownSymbol = createSymbol(SymbolFlags.Property, "unknown" as __String); var resolvingSymbol = createSymbol(0, InternalSymbolName.Resolving); @@ -6496,6 +6499,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } return symbolToTypeNode(type.symbol, context, SymbolFlags.Type); } + if (type.flags & TypeFlags.PrivateNameType) { + context.approximateLength += (type as PrivateNameType).value.length; + return factory.createPrivateNameTypeNode(factory.createPrivateIdentifier((type as PrivateNameType).value)); + } if (type.flags & TypeFlags.StringLiteral) { context.approximateLength += (type as StringLiteralType).value.length + 2; return factory.createLiteralTypeNode(setEmitFlags(factory.createStringLiteral((type as StringLiteralType).value, !!(context.flags & NodeBuilderFlags.UseSingleQuotesForStringLiteralType)), EmitFlags.NoAsciiEscaping)); @@ -18277,7 +18284,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getLiteralTypeFromPropertyName(name: PropertyName | JsxAttributeName) { if (isPrivateIdentifier(name)) { - return neverType; + return getPrivateNameType(name); } if (isNumericLiteral(name)) { return getRegularTypeOfLiteralType(checkExpression(name)); @@ -19397,6 +19404,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return links.resolvedType; } + function getTypeFromPrivateNameTypeNode(node: PrivateNameTypeNode) { + const links = getNodeLinks(node); + if (!links.resolvedType) { + links.resolvedType = getPrivateNameType(node.name); + } + return links.resolvedType; + } + function resolveImportSymbolType(node: ImportTypeNode, links: NodeLinks, symbol: Symbol, meaning: SymbolFlags) { const resolvedSymbol = resolveSymbol(symbol); links.resolvedSymbol = resolvedSymbol; @@ -19705,6 +19720,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return esSymbolType; } + function getPrivateNameType(node: PrivateIdentifier) { + const name = unescapeLeadingUnderscores(node.escapedText); + const symbol = privateNameTypes.get(name) ? undefined : lookupSymbolForPrivateIdentifierDeclaration(node.escapedText, node); + if ( + symbol?.valueDeclaration && + isPrivateIdentifierClassElementDeclaration(symbol.valueDeclaration) + ) { + privateNameTypes.set(name, createLiteralType(TypeFlags.StringLiteral | TypeFlags.PrivateNameType, name, symbol) as PrivateNameType); + } + return privateNameTypes.get(name) ?? neverType; + } + function getThisType(node: Node): Type { const container = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); const parent = container && container.parent; @@ -19872,6 +19899,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.PropertyAccessExpression as TypeNodeSyntaxKind: const symbol = getSymbolAtLocation(node); return symbol ? getDeclaredTypeOfSymbol(symbol) : errorType; + case SyntaxKind.PrivateNameType: + return getTypeFromPrivateNameTypeNode(node as PrivateNameTypeNode); default: return errorType; } @@ -42187,6 +42216,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkTypeReferenceOrImport(node); } + function checkPrivateNameType(node: PrivateNameTypeNode) { + const containingClass = getContainingClass(node); + if (containingClass === undefined) { + grammarErrorOnNode(node.name, Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies); + } + } + function checkNamedTupleMember(node: NamedTupleMember) { if (node.dotDotDotToken && node.questionToken) { grammarErrorOnNode(node, Diagnostics.A_tuple_member_cannot_be_both_optional_and_rest); @@ -48293,6 +48329,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return checkTemplateLiteralType(node as TemplateLiteralTypeNode); case SyntaxKind.ImportType: return checkImportType(node as ImportTypeNode); + case SyntaxKind.PrivateNameType: + return checkPrivateNameType(node as PrivateNameTypeNode); case SyntaxKind.NamedTupleMember: return checkNamedTupleMember(node as NamedTupleMember); case SyntaxKind.JSDocAugmentsTag: diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 01a96579861f4..609c4a2582045 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -341,6 +341,7 @@ import { PrinterOptions, PrintHandlers, PrivateIdentifier, + PrivateNameTypeNode, PropertyAccessExpression, PropertyAssignment, PropertyDeclaration, @@ -1655,6 +1656,8 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri return emitTemplateTypeSpan(node as TemplateLiteralTypeSpan); case SyntaxKind.ImportType: return emitImportTypeNode(node as ImportTypeNode); + case SyntaxKind.PrivateNameType: + return emitPrivateNameType(node as PrivateNameTypeNode); // Binding patterns case SyntaxKind.ObjectBindingPattern: @@ -2560,6 +2563,10 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri emitTypeArguments(node, node.typeArguments); } + function emitPrivateNameType(node: PrivateNameTypeNode) { + emitExpression(node.name); + } + // // Binding patterns // diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts index 694262eeeb54a..28469577cf847 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -357,6 +357,7 @@ import { PrefixUnaryOperator, PrimaryExpression, PrivateIdentifier, + PrivateNameTypeNode, PrologueDirective, PropertyAccessChain, PropertyAccessExpression, @@ -621,6 +622,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode updateLiteralTypeNode, createTemplateLiteralType, updateTemplateLiteralType, + createPrivateNameTypeNode, + updatePrivateNameTypeNode, createObjectBindingPattern, updateObjectBindingPattern, createArrayBindingPattern, @@ -2769,6 +2772,21 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode : node; } + // @api + function createPrivateNameTypeNode(name: PrivateIdentifier) { + const node = createBaseNode(SyntaxKind.PrivateNameType); + node.name = name; + node.transformFlags = TransformFlags.ContainsTypeScript; + return node; + } + + // @api + function updatePrivateNameTypeNode(node: PrivateNameTypeNode, name: PrivateIdentifier) { + return node.name !== name + ? update(createPrivateNameTypeNode(name), node) + : node; + } + // // Binding Patterns // diff --git a/src/compiler/factory/nodeTests.ts b/src/compiler/factory/nodeTests.ts index 8aa4bb02e83d2..d7a2b62d66e34 100644 --- a/src/compiler/factory/nodeTests.ts +++ b/src/compiler/factory/nodeTests.ts @@ -172,6 +172,7 @@ import { PostfixUnaryExpression, PrefixUnaryExpression, PrivateIdentifier, + PrivateNameTypeNode, PropertyAccessExpression, PropertyAssignment, PropertyDeclaration, @@ -557,6 +558,10 @@ export function isTemplateLiteralTypeNode(node: Node): node is TemplateLiteralTy return node.kind === SyntaxKind.TemplateLiteralType; } +export function isPrivateNameTypeNode(node: Node): node is PrivateNameTypeNode { + return node.kind === SyntaxKind.PrivateNameType; +} + // Binding patterns export function isObjectBindingPattern(node: Node): node is ObjectBindingPattern { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 8c69cccba1282..ab1ab453f5722 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -307,6 +307,7 @@ import { PrefixUnaryOperator, PrimaryExpression, PrivateIdentifier, + PrivateNameTypeNode, PropertyAccessEntityNameExpression, PropertyAccessExpression, PropertyAssignment, @@ -718,6 +719,9 @@ const forEachChildTable: ForEachChildTable = { [SyntaxKind.LiteralType]: function forEachChildInLiteralType(node: LiteralTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.literal); }, + [SyntaxKind.PrivateNameType]: function forEachChildInPrivateNameType(node: PrivateNameTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.name); + }, [SyntaxKind.NamedTupleMember]: function forEachChildInNamedTupleMember(node: NamedTupleMember, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.dotDotDotToken) || visitNode(cbNode, node.name) || @@ -4692,6 +4696,7 @@ namespace Parser { case SyntaxKind.AssertsKeyword: case SyntaxKind.NoSubstitutionTemplateLiteral: case SyntaxKind.TemplateHead: + case SyntaxKind.PrivateIdentifier: return true; case SyntaxKind.FunctionKeyword: return !inStartOfParameter; @@ -4939,6 +4944,11 @@ namespace Parser { if (contextFlags & NodeFlags.TypeExcludesFlags) { return doOutsideOfContext(NodeFlags.TypeExcludesFlags, parseType); } + if (token() === SyntaxKind.PrivateIdentifier) { + const pos = getNodePos(); + const name = parsePrivateIdentifier(); + return finishNode(factory.createPrivateNameTypeNode(name), pos); + } if (isStartOfFunctionTypeOrConstructorType()) { return parseFunctionOrConstructorType(); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index f6ca75a68e17d..9c01ef8c718d0 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -270,6 +270,7 @@ export const enum SyntaxKind { TemplateLiteralType, TemplateLiteralTypeSpan, ImportType, + PrivateNameType, // Binding patterns ObjectBindingPattern, ArrayBindingPattern, @@ -721,6 +722,7 @@ export type TypeNodeSyntaxKind = | SyntaxKind.TemplateLiteralType | SyntaxKind.TemplateLiteralTypeSpan | SyntaxKind.ImportType + | SyntaxKind.PrivateNameType | SyntaxKind.ExpressionWithTypeArguments | SyntaxKind.JSDocTypeExpression | SyntaxKind.JSDocAllType @@ -1096,6 +1098,7 @@ export type HasChildren = | LiteralTypeNode | TemplateLiteralTypeNode | TemplateLiteralTypeSpan + | PrivateNameTypeNode | ObjectBindingPattern | ArrayBindingPattern | BindingElement @@ -2383,6 +2386,11 @@ export interface TemplateLiteralTypeSpan extends TypeNode { readonly literal: TemplateMiddle | TemplateTail; } +export interface PrivateNameTypeNode extends TypeNode { + readonly kind: SyntaxKind.PrivateNameType; + readonly name: PrivateIdentifier; +} + // Note: 'brands' in our syntax nodes serve to give us a small amount of nominal typing. // Consider 'Expression'. Without the brand, 'Expression' is actually no different // (structurally) than 'Node'. Because of this you can pass any Node to a function that @@ -6300,6 +6308,8 @@ export const enum TypeFlags { Reserved1 = 1 << 29, // Used by union/intersection type construction /** @internal */ Reserved2 = 1 << 30, // Used by union/intersection type construction + /** @internal */ + PrivateNameType = 1 << 31, /** @internal */ AnyOrUnknown = Any | Unknown, @@ -6438,6 +6448,9 @@ export interface NumberLiteralType extends LiteralType { export interface BigIntLiteralType extends LiteralType { value: PseudoBigInt; } +export interface PrivateNameType extends StringLiteralType { + symbol: Symbol; +} // Enum types (TypeFlags.Enum) export interface EnumType extends FreshableType { @@ -8853,6 +8866,8 @@ export interface NodeFactory { updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]): LiteralTypeNode; createTemplateLiteralType(head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]): TemplateLiteralTypeNode; updateTemplateLiteralType(node: TemplateLiteralTypeNode, head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]): TemplateLiteralTypeNode; + createPrivateNameTypeNode(name: PrivateIdentifier): PrivateNameTypeNode; + updatePrivateNameTypeNode(node: PrivateNameTypeNode, name: PrivateIdentifier): PrivateNameTypeNode; // // Binding Patterns diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 5755369134d8a..a527f2168b1d6 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -477,6 +477,7 @@ import { PrinterOptions, PrintHandlers, PrivateIdentifier, + PrivateNameType, ProjectReference, PrologueDirective, PropertyAccessEntityNameExpression, @@ -11057,18 +11058,21 @@ export function intrinsicTagNameToString(node: Identifier | JsxNamespacedName): * Indicates whether a type can be used as a property name. * @internal */ -export function isTypeUsableAsPropertyName(type: Type): type is StringLiteralType | NumberLiteralType | UniqueESSymbolType { - return !!(type.flags & TypeFlags.StringOrNumberLiteralOrUnique); +export function isTypeUsableAsPropertyName(type: Type): type is StringLiteralType | NumberLiteralType | UniqueESSymbolType | PrivateNameType { + return !!(type.flags & (TypeFlags.StringOrNumberLiteralOrUnique | TypeFlags.PrivateNameType)); } /** * Gets the symbolic name for a member from its type. * @internal */ -export function getPropertyNameFromType(type: StringLiteralType | NumberLiteralType | UniqueESSymbolType): __String { +export function getPropertyNameFromType(type: StringLiteralType | NumberLiteralType | UniqueESSymbolType | PrivateNameType): __String { if (type.flags & TypeFlags.UniqueESSymbol) { return (type as UniqueESSymbolType).escapedName; } + if (type.flags & TypeFlags.PrivateNameType) { + return (type as PrivateNameType).symbol.escapedName; + } if (type.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) { return escapeLeadingUnderscores("" + (type as StringLiteralType | NumberLiteralType).value); } diff --git a/src/compiler/visitorPublic.ts b/src/compiler/visitorPublic.ts index dbd49379e5750..638fd15949684 100644 --- a/src/compiler/visitorPublic.ts +++ b/src/compiler/visitorPublic.ts @@ -67,6 +67,7 @@ import { isObjectLiteralElementLike, isOptionalChain, isParameter, + isPrivateIdentifier, isPropertyAccessChain, isPropertyName, isQuestionDotToken, @@ -978,6 +979,13 @@ const visitEachChildTable: VisitEachChildTable = { ); }, + [SyntaxKind.PrivateNameType]: function visitEachChildOfPrivateIdentifier(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { + return context.factory.updatePrivateNameTypeNode( + node, + Debug.checkDefined(nodeVisitor(node.name, visitor, isPrivateIdentifier)), + ); + }, + // Binding patterns [SyntaxKind.ObjectBindingPattern]: function visitEachChildOfObjectBindingPattern(node, visitor, context, nodesVisitor, _nodeVisitor, _tokenVisitor) { return context.factory.updateObjectBindingPattern( diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 2531c9ea0413d..eb4bf4fb7c851 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3870,163 +3870,164 @@ declare namespace ts { TemplateLiteralType = 203, TemplateLiteralTypeSpan = 204, ImportType = 205, - ObjectBindingPattern = 206, - ArrayBindingPattern = 207, - BindingElement = 208, - ArrayLiteralExpression = 209, - ObjectLiteralExpression = 210, - PropertyAccessExpression = 211, - ElementAccessExpression = 212, - CallExpression = 213, - NewExpression = 214, - TaggedTemplateExpression = 215, - TypeAssertionExpression = 216, - ParenthesizedExpression = 217, - FunctionExpression = 218, - ArrowFunction = 219, - DeleteExpression = 220, - TypeOfExpression = 221, - VoidExpression = 222, - AwaitExpression = 223, - PrefixUnaryExpression = 224, - PostfixUnaryExpression = 225, - BinaryExpression = 226, - ConditionalExpression = 227, - TemplateExpression = 228, - YieldExpression = 229, - SpreadElement = 230, - ClassExpression = 231, - OmittedExpression = 232, - ExpressionWithTypeArguments = 233, - AsExpression = 234, - NonNullExpression = 235, - MetaProperty = 236, - SyntheticExpression = 237, - SatisfiesExpression = 238, - TemplateSpan = 239, - SemicolonClassElement = 240, - Block = 241, - EmptyStatement = 242, - VariableStatement = 243, - ExpressionStatement = 244, - IfStatement = 245, - DoStatement = 246, - WhileStatement = 247, - ForStatement = 248, - ForInStatement = 249, - ForOfStatement = 250, - ContinueStatement = 251, - BreakStatement = 252, - ReturnStatement = 253, - WithStatement = 254, - SwitchStatement = 255, - LabeledStatement = 256, - ThrowStatement = 257, - TryStatement = 258, - DebuggerStatement = 259, - VariableDeclaration = 260, - VariableDeclarationList = 261, - FunctionDeclaration = 262, - ClassDeclaration = 263, - InterfaceDeclaration = 264, - TypeAliasDeclaration = 265, - EnumDeclaration = 266, - ModuleDeclaration = 267, - ModuleBlock = 268, - CaseBlock = 269, - NamespaceExportDeclaration = 270, - ImportEqualsDeclaration = 271, - ImportDeclaration = 272, - ImportClause = 273, - NamespaceImport = 274, - NamedImports = 275, - ImportSpecifier = 276, - ExportAssignment = 277, - ExportDeclaration = 278, - NamedExports = 279, - NamespaceExport = 280, - ExportSpecifier = 281, - MissingDeclaration = 282, - ExternalModuleReference = 283, - JsxElement = 284, - JsxSelfClosingElement = 285, - JsxOpeningElement = 286, - JsxClosingElement = 287, - JsxFragment = 288, - JsxOpeningFragment = 289, - JsxClosingFragment = 290, - JsxAttribute = 291, - JsxAttributes = 292, - JsxSpreadAttribute = 293, - JsxExpression = 294, - JsxNamespacedName = 295, - CaseClause = 296, - DefaultClause = 297, - HeritageClause = 298, - CatchClause = 299, - ImportAttributes = 300, - ImportAttribute = 301, - /** @deprecated */ AssertClause = 300, - /** @deprecated */ AssertEntry = 301, - /** @deprecated */ ImportTypeAssertionContainer = 302, - PropertyAssignment = 303, - ShorthandPropertyAssignment = 304, - SpreadAssignment = 305, - EnumMember = 306, - SourceFile = 307, - Bundle = 308, - JSDocTypeExpression = 309, - JSDocNameReference = 310, - JSDocMemberName = 311, - JSDocAllType = 312, - JSDocUnknownType = 313, - JSDocNullableType = 314, - JSDocNonNullableType = 315, - JSDocOptionalType = 316, - JSDocFunctionType = 317, - JSDocVariadicType = 318, - JSDocNamepathType = 319, - JSDoc = 320, + PrivateNameType = 206, + ObjectBindingPattern = 207, + ArrayBindingPattern = 208, + BindingElement = 209, + ArrayLiteralExpression = 210, + ObjectLiteralExpression = 211, + PropertyAccessExpression = 212, + ElementAccessExpression = 213, + CallExpression = 214, + NewExpression = 215, + TaggedTemplateExpression = 216, + TypeAssertionExpression = 217, + ParenthesizedExpression = 218, + FunctionExpression = 219, + ArrowFunction = 220, + DeleteExpression = 221, + TypeOfExpression = 222, + VoidExpression = 223, + AwaitExpression = 224, + PrefixUnaryExpression = 225, + PostfixUnaryExpression = 226, + BinaryExpression = 227, + ConditionalExpression = 228, + TemplateExpression = 229, + YieldExpression = 230, + SpreadElement = 231, + ClassExpression = 232, + OmittedExpression = 233, + ExpressionWithTypeArguments = 234, + AsExpression = 235, + NonNullExpression = 236, + MetaProperty = 237, + SyntheticExpression = 238, + SatisfiesExpression = 239, + TemplateSpan = 240, + SemicolonClassElement = 241, + Block = 242, + EmptyStatement = 243, + VariableStatement = 244, + ExpressionStatement = 245, + IfStatement = 246, + DoStatement = 247, + WhileStatement = 248, + ForStatement = 249, + ForInStatement = 250, + ForOfStatement = 251, + ContinueStatement = 252, + BreakStatement = 253, + ReturnStatement = 254, + WithStatement = 255, + SwitchStatement = 256, + LabeledStatement = 257, + ThrowStatement = 258, + TryStatement = 259, + DebuggerStatement = 260, + VariableDeclaration = 261, + VariableDeclarationList = 262, + FunctionDeclaration = 263, + ClassDeclaration = 264, + InterfaceDeclaration = 265, + TypeAliasDeclaration = 266, + EnumDeclaration = 267, + ModuleDeclaration = 268, + ModuleBlock = 269, + CaseBlock = 270, + NamespaceExportDeclaration = 271, + ImportEqualsDeclaration = 272, + ImportDeclaration = 273, + ImportClause = 274, + NamespaceImport = 275, + NamedImports = 276, + ImportSpecifier = 277, + ExportAssignment = 278, + ExportDeclaration = 279, + NamedExports = 280, + NamespaceExport = 281, + ExportSpecifier = 282, + MissingDeclaration = 283, + ExternalModuleReference = 284, + JsxElement = 285, + JsxSelfClosingElement = 286, + JsxOpeningElement = 287, + JsxClosingElement = 288, + JsxFragment = 289, + JsxOpeningFragment = 290, + JsxClosingFragment = 291, + JsxAttribute = 292, + JsxAttributes = 293, + JsxSpreadAttribute = 294, + JsxExpression = 295, + JsxNamespacedName = 296, + CaseClause = 297, + DefaultClause = 298, + HeritageClause = 299, + CatchClause = 300, + ImportAttributes = 301, + ImportAttribute = 302, + /** @deprecated */ AssertClause = 301, + /** @deprecated */ AssertEntry = 302, + /** @deprecated */ ImportTypeAssertionContainer = 303, + PropertyAssignment = 304, + ShorthandPropertyAssignment = 305, + SpreadAssignment = 306, + EnumMember = 307, + SourceFile = 308, + Bundle = 309, + JSDocTypeExpression = 310, + JSDocNameReference = 311, + JSDocMemberName = 312, + JSDocAllType = 313, + JSDocUnknownType = 314, + JSDocNullableType = 315, + JSDocNonNullableType = 316, + JSDocOptionalType = 317, + JSDocFunctionType = 318, + JSDocVariadicType = 319, + JSDocNamepathType = 320, + JSDoc = 321, /** @deprecated Use SyntaxKind.JSDoc */ - JSDocComment = 320, - JSDocText = 321, - JSDocTypeLiteral = 322, - JSDocSignature = 323, - JSDocLink = 324, - JSDocLinkCode = 325, - JSDocLinkPlain = 326, - JSDocTag = 327, - JSDocAugmentsTag = 328, - JSDocImplementsTag = 329, - JSDocAuthorTag = 330, - JSDocDeprecatedTag = 331, - JSDocClassTag = 332, - JSDocPublicTag = 333, - JSDocPrivateTag = 334, - JSDocProtectedTag = 335, - JSDocReadonlyTag = 336, - JSDocOverrideTag = 337, - JSDocCallbackTag = 338, - JSDocOverloadTag = 339, - JSDocEnumTag = 340, - JSDocParameterTag = 341, - JSDocReturnTag = 342, - JSDocThisTag = 343, - JSDocTypeTag = 344, - JSDocTemplateTag = 345, - JSDocTypedefTag = 346, - JSDocSeeTag = 347, - JSDocPropertyTag = 348, - JSDocThrowsTag = 349, - JSDocSatisfiesTag = 350, - JSDocImportTag = 351, - SyntaxList = 352, - NotEmittedStatement = 353, - NotEmittedTypeElement = 354, - PartiallyEmittedExpression = 355, - CommaListExpression = 356, - SyntheticReferenceExpression = 357, - Count = 358, + JSDocComment = 321, + JSDocText = 322, + JSDocTypeLiteral = 323, + JSDocSignature = 324, + JSDocLink = 325, + JSDocLinkCode = 326, + JSDocLinkPlain = 327, + JSDocTag = 328, + JSDocAugmentsTag = 329, + JSDocImplementsTag = 330, + JSDocAuthorTag = 331, + JSDocDeprecatedTag = 332, + JSDocClassTag = 333, + JSDocPublicTag = 334, + JSDocPrivateTag = 335, + JSDocProtectedTag = 336, + JSDocReadonlyTag = 337, + JSDocOverrideTag = 338, + JSDocCallbackTag = 339, + JSDocOverloadTag = 340, + JSDocEnumTag = 341, + JSDocParameterTag = 342, + JSDocReturnTag = 343, + JSDocThisTag = 344, + JSDocTypeTag = 345, + JSDocTemplateTag = 346, + JSDocTypedefTag = 347, + JSDocSeeTag = 348, + JSDocPropertyTag = 349, + JSDocThrowsTag = 350, + JSDocSatisfiesTag = 351, + JSDocImportTag = 352, + SyntaxList = 353, + NotEmittedStatement = 354, + NotEmittedTypeElement = 355, + PartiallyEmittedExpression = 356, + CommaListExpression = 357, + SyntheticReferenceExpression = 358, + Count = 359, FirstAssignment = 64, LastAssignment = 79, FirstCompoundAssignment = 65, @@ -4051,13 +4052,13 @@ declare namespace ts { LastTemplateToken = 18, FirstBinaryOperator = 30, LastBinaryOperator = 79, - FirstStatement = 243, - LastStatement = 259, + FirstStatement = 244, + LastStatement = 260, FirstNode = 166, - FirstJSDocNode = 309, - LastJSDocNode = 351, - FirstJSDocTagNode = 327, - LastJSDocTagNode = 351, + FirstJSDocNode = 310, + LastJSDocNode = 352, + FirstJSDocTagNode = 328, + LastJSDocTagNode = 352, } type TriviaSyntaxKind = SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia | SyntaxKind.NewLineTrivia | SyntaxKind.WhitespaceTrivia | SyntaxKind.ShebangTrivia | SyntaxKind.ConflictMarkerTrivia; type LiteralSyntaxKind = SyntaxKind.NumericLiteral | SyntaxKind.BigIntLiteral | SyntaxKind.StringLiteral | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.RegularExpressionLiteral | SyntaxKind.NoSubstitutionTemplateLiteral; @@ -4828,6 +4829,10 @@ declare namespace ts { readonly type: TypeNode; readonly literal: TemplateMiddle | TemplateTail; } + interface PrivateNameTypeNode extends TypeNode { + readonly kind: SyntaxKind.PrivateNameType; + readonly name: PrivateIdentifier; + } interface Expression extends Node { _expressionBrand: any; } @@ -6671,6 +6676,9 @@ declare namespace ts { interface BigIntLiteralType extends LiteralType { value: PseudoBigInt; } + interface PrivateNameType extends StringLiteralType { + symbol: Symbol; + } interface EnumType extends FreshableType { } enum ObjectFlags { @@ -7568,6 +7576,8 @@ declare namespace ts { updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]): LiteralTypeNode; createTemplateLiteralType(head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]): TemplateLiteralTypeNode; updateTemplateLiteralType(node: TemplateLiteralTypeNode, head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]): TemplateLiteralTypeNode; + createPrivateNameTypeNode(name: PrivateIdentifier): PrivateNameTypeNode; + updatePrivateNameTypeNode(node: PrivateNameTypeNode, name: PrivateIdentifier): PrivateNameTypeNode; createObjectBindingPattern(elements: readonly BindingElement[]): ObjectBindingPattern; updateObjectBindingPattern(node: ObjectBindingPattern, elements: readonly BindingElement[]): ObjectBindingPattern; createArrayBindingPattern(elements: readonly ArrayBindingElement[]): ArrayBindingPattern; @@ -8977,6 +8987,7 @@ declare namespace ts { function isImportTypeNode(node: Node): node is ImportTypeNode; function isTemplateLiteralTypeSpan(node: Node): node is TemplateLiteralTypeSpan; function isTemplateLiteralTypeNode(node: Node): node is TemplateLiteralTypeNode; + function isPrivateNameTypeNode(node: Node): node is PrivateNameTypeNode; function isObjectBindingPattern(node: Node): node is ObjectBindingPattern; function isArrayBindingPattern(node: Node): node is ArrayBindingPattern; function isBindingElement(node: Node): node is BindingElement; diff --git a/tests/baselines/reference/privateNameInTypeQuery.errors.txt b/tests/baselines/reference/privateNameInTypeQuery.errors.txt new file mode 100644 index 0000000000000..49af9712b3fae --- /dev/null +++ b/tests/baselines/reference/privateNameInTypeQuery.errors.txt @@ -0,0 +1,33 @@ +privateNameInTypeQuery.ts(6,15): error TS2322: Type 'number' is not assignable to type 'this["a"]'. + 'this["a"]' could be instantiated with an arbitrary type which could be unrelated to 'number'. +privateNameInTypeQuery.ts(9,15): error TS2322: Type 'number' is not assignable to type 'this[#b]'. + 'this[#b]' could be instantiated with an arbitrary type which could be unrelated to 'number'. +privateNameInTypeQuery.ts(16,19): error TS18016: Private identifiers are not allowed outside class bodies. + + +==== privateNameInTypeQuery.ts (3 errors) ==== + class C { + a = 'a'; + #b = 'b'; + + constructor() { + const a: typeof this['a'] = 1; + ~ +!!! error TS2322: Type 'number' is not assignable to type 'this["a"]'. +!!! error TS2322: 'this["a"]' could be instantiated with an arbitrary type which could be unrelated to 'number'. + const b: typeof this['a'] = ''; // ok + + const c: typeof this[#b] = 1; + ~ +!!! error TS2322: Type 'number' is not assignable to type 'this[#b]'. +!!! error TS2322: 'this[#b]' could be instantiated with an arbitrary type which could be unrelated to 'number'. + const d: typeof this[#b] = ''; // ok + } + } + + const c = new C(); + const a: typeof c['a'] = ''; + const b: typeof c[#b] = ''; + ~~ +!!! error TS18016: Private identifiers are not allowed outside class bodies. + \ No newline at end of file diff --git a/tests/baselines/reference/privateNameInTypeQuery.js b/tests/baselines/reference/privateNameInTypeQuery.js new file mode 100644 index 0000000000000..8f44f4d0fb25a --- /dev/null +++ b/tests/baselines/reference/privateNameInTypeQuery.js @@ -0,0 +1,36 @@ +//// [tests/cases/conformance/classes/members/privateNames/privateNameInTypeQuery.ts] //// + +//// [privateNameInTypeQuery.ts] +class C { + a = 'a'; + #b = 'b'; + + constructor() { + const a: typeof this['a'] = 1; + const b: typeof this['a'] = ''; // ok + + const c: typeof this[#b] = 1; + const d: typeof this[#b] = ''; // ok + } +} + +const c = new C(); +const a: typeof c['a'] = ''; +const b: typeof c[#b] = ''; + + +//// [privateNameInTypeQuery.js] +"use strict"; +class C { + a = 'a'; + #b = 'b'; + constructor() { + const a = 1; + const b = ''; // ok + const c = 1; + const d = ''; // ok + } +} +const c = new C(); +const a = ''; +const b = ''; diff --git a/tests/baselines/reference/privateNameInTypeQuery.symbols b/tests/baselines/reference/privateNameInTypeQuery.symbols new file mode 100644 index 0000000000000..e6c6d715fdec4 --- /dev/null +++ b/tests/baselines/reference/privateNameInTypeQuery.symbols @@ -0,0 +1,43 @@ +//// [tests/cases/conformance/classes/members/privateNames/privateNameInTypeQuery.ts] //// + +=== privateNameInTypeQuery.ts === +class C { +>C : Symbol(C, Decl(privateNameInTypeQuery.ts, 0, 0)) + + a = 'a'; +>a : Symbol(C.a, Decl(privateNameInTypeQuery.ts, 0, 9)) + + #b = 'b'; +>#b : Symbol(C.#b, Decl(privateNameInTypeQuery.ts, 1, 12)) + + constructor() { + const a: typeof this['a'] = 1; +>a : Symbol(a, Decl(privateNameInTypeQuery.ts, 5, 13)) +>this : Symbol(C, Decl(privateNameInTypeQuery.ts, 0, 0)) + + const b: typeof this['a'] = ''; // ok +>b : Symbol(b, Decl(privateNameInTypeQuery.ts, 6, 13)) +>this : Symbol(C, Decl(privateNameInTypeQuery.ts, 0, 0)) + + const c: typeof this[#b] = 1; +>c : Symbol(c, Decl(privateNameInTypeQuery.ts, 8, 13)) +>this : Symbol(C, Decl(privateNameInTypeQuery.ts, 0, 0)) + + const d: typeof this[#b] = ''; // ok +>d : Symbol(d, Decl(privateNameInTypeQuery.ts, 9, 13)) +>this : Symbol(C, Decl(privateNameInTypeQuery.ts, 0, 0)) + } +} + +const c = new C(); +>c : Symbol(c, Decl(privateNameInTypeQuery.ts, 13, 5)) +>C : Symbol(C, Decl(privateNameInTypeQuery.ts, 0, 0)) + +const a: typeof c['a'] = ''; +>a : Symbol(a, Decl(privateNameInTypeQuery.ts, 14, 5)) +>c : Symbol(c, Decl(privateNameInTypeQuery.ts, 13, 5)) + +const b: typeof c[#b] = ''; +>b : Symbol(b, Decl(privateNameInTypeQuery.ts, 15, 5)) +>c : Symbol(c, Decl(privateNameInTypeQuery.ts, 13, 5)) + diff --git a/tests/baselines/reference/privateNameInTypeQuery.types b/tests/baselines/reference/privateNameInTypeQuery.types new file mode 100644 index 0000000000000..c33a4ce28d9fe --- /dev/null +++ b/tests/baselines/reference/privateNameInTypeQuery.types @@ -0,0 +1,78 @@ +//// [tests/cases/conformance/classes/members/privateNames/privateNameInTypeQuery.ts] //// + +=== privateNameInTypeQuery.ts === +class C { +>C : C +> : ^ + + a = 'a'; +>a : string +> : ^^^^^^ +>'a' : "a" +> : ^^^ + + #b = 'b'; +>#b : string +> : ^^^^^^ +>'b' : "b" +> : ^^^ + + constructor() { + const a: typeof this['a'] = 1; +>a : this["a"] +> : ^^^^^^^^^ +>this : this +> : ^^^^ +>1 : 1 +> : ^ + + const b: typeof this['a'] = ''; // ok +>b : this["a"] +> : ^^^^^^^^^ +>this : this +> : ^^^^ +>'' : "" +> : ^^ + + const c: typeof this[#b] = 1; +>c : this[#b] +> : ^^^^^^^^ +>this : this +> : ^^^^ +>1 : 1 +> : ^ + + const d: typeof this[#b] = ''; // ok +>d : this[#b] +> : ^^^^^^^^ +>this : this +> : ^^^^ +>'' : "" +> : ^^ + } +} + +const c = new C(); +>c : C +> : ^ +>new C() : C +> : ^ +>C : typeof C +> : ^^^^^^^^ + +const a: typeof c['a'] = ''; +>a : string +> : ^^^^^^ +>c : C +> : ^ +>'' : "" +> : ^^ + +const b: typeof c[#b] = ''; +>b : string +> : ^^^^^^ +>c : C +> : ^ +>'' : "" +> : ^^ + diff --git a/tests/baselines/reference/privateNamesAndIndexedAccess.errors.txt b/tests/baselines/reference/privateNamesAndIndexedAccess.errors.txt index f5ab847471bd1..3fb86e1ce87dd 100644 --- a/tests/baselines/reference/privateNamesAndIndexedAccess.errors.txt +++ b/tests/baselines/reference/privateNamesAndIndexedAccess.errors.txt @@ -1,29 +1,14 @@ -privateNamesAndIndexedAccess.ts(7,28): error TS1005: ']' expected. -privateNamesAndIndexedAccess.ts(7,28): error TS7005: Variable '#bar' implicitly has an 'any' type. -privateNamesAndIndexedAccess.ts(7,32): error TS1005: ',' expected. -privateNamesAndIndexedAccess.ts(7,34): error TS1134: Variable declaration expected. -privateNamesAndIndexedAccess.ts(7,36): error TS1134: Variable declaration expected. privateNamesAndIndexedAccess.ts(9,28): error TS2339: Property '#bar' does not exist on type 'C'. -==== privateNamesAndIndexedAccess.ts (6 errors) ==== +==== privateNamesAndIndexedAccess.ts (1 errors) ==== class C { foo = 3; #bar = 3; constructor () { const ok: C["foo"] = 3; - // not supported yet, could support in future: - const badForNow: C[#bar] = 3; // Error - ~~~~ -!!! error TS1005: ']' expected. - ~~~~ -!!! error TS7005: Variable '#bar' implicitly has an 'any' type. - ~ -!!! error TS1005: ',' expected. - ~ -!!! error TS1134: Variable declaration expected. - ~ -!!! error TS1134: Variable declaration expected. + const badForNow: C[#bar] = 3; + // will never use this syntax, already taken: const badAlways: C["#bar"] = 3; // Error ~~~~~~ diff --git a/tests/baselines/reference/privateNamesAndIndexedAccess.js b/tests/baselines/reference/privateNamesAndIndexedAccess.js index 956ed78c15cdc..15ed769242d5d 100644 --- a/tests/baselines/reference/privateNamesAndIndexedAccess.js +++ b/tests/baselines/reference/privateNamesAndIndexedAccess.js @@ -6,8 +6,8 @@ class C { #bar = 3; constructor () { const ok: C["foo"] = 3; - // not supported yet, could support in future: - const badForNow: C[#bar] = 3; // Error + const badForNow: C[#bar] = 3; + // will never use this syntax, already taken: const badAlways: C["#bar"] = 3; // Error } @@ -22,9 +22,7 @@ class C { this.foo = 3; _C_bar.set(this, 3); const ok = 3; - // not supported yet, could support in future: - const badForNow, #bar; - 3; // Error + const badForNow = 3; // will never use this syntax, already taken: const badAlways = 3; // Error } diff --git a/tests/baselines/reference/privateNamesAndIndexedAccess.symbols b/tests/baselines/reference/privateNamesAndIndexedAccess.symbols index 59572ddc44972..b8cfa85ac5f32 100644 --- a/tests/baselines/reference/privateNamesAndIndexedAccess.symbols +++ b/tests/baselines/reference/privateNamesAndIndexedAccess.symbols @@ -15,11 +15,9 @@ class C { >ok : Symbol(ok, Decl(privateNamesAndIndexedAccess.ts, 4, 13)) >C : Symbol(C, Decl(privateNamesAndIndexedAccess.ts, 0, 0)) - // not supported yet, could support in future: - const badForNow: C[#bar] = 3; // Error ->badForNow : Symbol(badForNow, Decl(privateNamesAndIndexedAccess.ts, 6, 13)) + const badForNow: C[#bar] = 3; +>badForNow : Symbol(badForNow, Decl(privateNamesAndIndexedAccess.ts, 5, 13)) >C : Symbol(C, Decl(privateNamesAndIndexedAccess.ts, 0, 0)) ->#bar : Symbol(#bar, Decl(privateNamesAndIndexedAccess.ts, 6, 27)) // will never use this syntax, already taken: const badAlways: C["#bar"] = 3; // Error diff --git a/tests/baselines/reference/privateNamesAndIndexedAccess.types b/tests/baselines/reference/privateNamesAndIndexedAccess.types index f497fe963d30d..dc5f57f2e3492 100644 --- a/tests/baselines/reference/privateNamesAndIndexedAccess.types +++ b/tests/baselines/reference/privateNamesAndIndexedAccess.types @@ -24,12 +24,9 @@ class C { >3 : 3 > : ^ - // not supported yet, could support in future: - const badForNow: C[#bar] = 3; // Error ->badForNow : C[] -> : ^^^ ->#bar : any -> : ^^^ + const badForNow: C[#bar] = 3; +>badForNow : number +> : ^^^^^^ >3 : 3 > : ^ diff --git a/tests/baselines/reference/privateNamesAndkeyof.errors.txt b/tests/baselines/reference/privateNamesAndkeyof.errors.txt index ce6200131fefc..f9a246f6f9996 100644 --- a/tests/baselines/reference/privateNamesAndkeyof.errors.txt +++ b/tests/baselines/reference/privateNamesAndkeyof.errors.txt @@ -1,9 +1,9 @@ privateNamesAndkeyof.ts(14,1): error TS2322: Type '"#fooField"' is not assignable to type 'keyof A'. privateNamesAndkeyof.ts(15,1): error TS2322: Type '"#fooMethod"' is not assignable to type 'keyof A'. privateNamesAndkeyof.ts(16,1): error TS2322: Type '"#fooProp"' is not assignable to type 'keyof A'. -privateNamesAndkeyof.ts(18,1): error TS2322: Type '"fooField"' is not assignable to type 'keyof A'. -privateNamesAndkeyof.ts(19,1): error TS2322: Type '"fooMethod"' is not assignable to type 'keyof A'. -privateNamesAndkeyof.ts(20,1): error TS2322: Type '"fooProp"' is not assignable to type 'keyof A'. +privateNamesAndkeyof.ts(18,1): error TS2820: Type '"fooField"' is not assignable to type 'keyof A'. Did you mean '#fooField'? +privateNamesAndkeyof.ts(19,1): error TS2820: Type '"fooMethod"' is not assignable to type 'keyof A'. Did you mean '#fooMethod'? +privateNamesAndkeyof.ts(20,1): error TS2820: Type '"fooProp"' is not assignable to type 'keyof A'. Did you mean '#fooProp'? ==== privateNamesAndkeyof.ts (6 errors) ==== @@ -32,11 +32,11 @@ privateNamesAndkeyof.ts(20,1): error TS2322: Type '"fooProp"' is not assignable k = "fooField"; // Error ~ -!!! error TS2322: Type '"fooField"' is not assignable to type 'keyof A'. +!!! error TS2820: Type '"fooField"' is not assignable to type 'keyof A'. Did you mean '#fooField'? k = "fooMethod"; // Error ~ -!!! error TS2322: Type '"fooMethod"' is not assignable to type 'keyof A'. +!!! error TS2820: Type '"fooMethod"' is not assignable to type 'keyof A'. Did you mean '#fooMethod'? k = "fooProp"; // Error ~ -!!! error TS2322: Type '"fooProp"' is not assignable to type 'keyof A'. +!!! error TS2820: Type '"fooProp"' is not assignable to type 'keyof A'. Did you mean '#fooProp'? \ No newline at end of file diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameInTypeQuery.ts b/tests/cases/conformance/classes/members/privateNames/privateNameInTypeQuery.ts new file mode 100644 index 0000000000000..48683e4478276 --- /dev/null +++ b/tests/cases/conformance/classes/members/privateNames/privateNameInTypeQuery.ts @@ -0,0 +1,19 @@ +// @strict: true +// @target: esnext + +class C { + a = 'a'; + #b = 'b'; + + constructor() { + const a: typeof this['a'] = 1; + const b: typeof this['a'] = ''; // ok + + const c: typeof this[#b] = 1; + const d: typeof this[#b] = ''; // ok + } +} + +const c = new C(); +const a: typeof c['a'] = ''; +const b: typeof c[#b] = ''; diff --git a/tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts b/tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts index b1b5c88ca347b..55baf4382a95a 100644 --- a/tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts +++ b/tests/cases/conformance/classes/members/privateNames/privateNamesAndIndexedAccess.ts @@ -7,8 +7,8 @@ class C { #bar = 3; constructor () { const ok: C["foo"] = 3; - // not supported yet, could support in future: - const badForNow: C[#bar] = 3; // Error + const badForNow: C[#bar] = 3; + // will never use this syntax, already taken: const badAlways: C["#bar"] = 3; // Error }