diff --git a/_packages/native-preview/src/ast/ast.generated.ts b/_packages/native-preview/src/ast/ast.generated.ts index d7b1b7d55bb..722b1e18aeb 100644 --- a/_packages/native-preview/src/ast/ast.generated.ts +++ b/_packages/native-preview/src/ast/ast.generated.ts @@ -508,7 +508,7 @@ export interface PrivateIdentifier extends PrimaryExpressionBase { export interface QualifiedName extends NodeBase { readonly kind: SyntaxKind.QualifiedName; readonly left: EntityName; - readonly right: Identifier; + readonly right: MemberName; } export interface ComputedPropertyName extends NodeBase { readonly kind: SyntaxKind.ComputedPropertyName; diff --git a/_packages/native-preview/src/ast/factory.generated.ts b/_packages/native-preview/src/ast/factory.generated.ts index a84c318a386..f8c1ca889f2 100644 --- a/_packages/native-preview/src/ast/factory.generated.ts +++ b/_packages/native-preview/src/ast/factory.generated.ts @@ -1673,7 +1673,7 @@ export function createPrivateIdentifier(text: string): PrivateIdentifier { }) as unknown as PrivateIdentifier; } -export function createQualifiedName(left: EntityName, right: Identifier): QualifiedName { +export function createQualifiedName(left: EntityName, right: MemberName): QualifiedName { return new NodeObject(SyntaxKind.QualifiedName, { left, right, @@ -3105,7 +3105,7 @@ export function createJSDocPropertyTag(tagName: Identifier, name: EntityName, is }) as unknown as JSDocPropertyTag; } -export function updateQualifiedName(node: QualifiedName, left: EntityName, right: Identifier): QualifiedName { +export function updateQualifiedName(node: QualifiedName, left: EntityName, right: MemberName): QualifiedName { return node.left !== left || node.right !== right ? createQualifiedName(left, right) : node; } diff --git a/_packages/native-preview/src/ast/visitor.generated.ts b/_packages/native-preview/src/ast/visitor.generated.ts index 03829048b5e..6267788908c 100644 --- a/_packages/native-preview/src/ast/visitor.generated.ts +++ b/_packages/native-preview/src/ast/visitor.generated.ts @@ -515,7 +515,7 @@ type VisitEachChildFunction = (node: any, visitor: Visitor) => Node; const visitEachChildTable: Record = { [SyntaxKind.QualifiedName]: (node: QualifiedName, visitor: Visitor): QualifiedName => { const _left = visitNode(node.left, visitor, isEntityName); - const _right = visitNode(node.right, visitor, isIdentifier); + const _right = visitNode(node.right, visitor, isMemberName); return updateQualifiedName(node, _left, _right); }, [SyntaxKind.ComputedPropertyName]: (node: ComputedPropertyName, visitor: Visitor): ComputedPropertyName => { diff --git a/_scripts/ast.json b/_scripts/ast.json index 852cc59e09d..3c85511b463 100644 --- a/_scripts/ast.json +++ b/_scripts/ast.json @@ -1258,7 +1258,7 @@ }, { "name": "Right", - "type": "Identifier" + "type": "MemberName" } ] }, diff --git a/internal/ast/ast_generated.go b/internal/ast/ast_generated.go index 08bb3fdae0a..34c7e1201d0 100644 --- a/internal/ast/ast_generated.go +++ b/internal/ast/ast_generated.go @@ -672,17 +672,17 @@ type QualifiedName struct { FlowNodeBase CompositeBase Left *EntityName - Right *IdentifierNode + Right *MemberName } -func (f *NodeFactory) NewQualifiedName(left *EntityName, right *IdentifierNode) *Node { +func (f *NodeFactory) NewQualifiedName(left *EntityName, right *MemberName) *Node { data := &QualifiedName{} data.Left = left data.Right = right return f.newNode(KindQualifiedName, data) } -func (f *NodeFactory) UpdateQualifiedName(node *QualifiedName, left *EntityName, right *IdentifierNode) *Node { +func (f *NodeFactory) UpdateQualifiedName(node *QualifiedName, left *EntityName, right *MemberName) *Node { if left != node.Left || right != node.Right { return updateNode(f.NewQualifiedName(left, right), node.AsNode(), f.hooks) } diff --git a/internal/diagnostics/diagnostics_generated.go b/internal/diagnostics/diagnostics_generated.go index 8719c9d1ad1..abbb098d275 100644 --- a/internal/diagnostics/diagnostics_generated.go +++ b/internal/diagnostics/diagnostics_generated.go @@ -3468,6 +3468,8 @@ var This_syntax_is_reserved_in_files_with_the_mts_or_cts_extension_Add_a_trailin var A_mapped_type_may_not_declare_properties_or_methods = &Message{code: 7061, category: CategoryError, key: "A_mapped_type_may_not_declare_properties_or_methods_7061", text: "A mapped type may not declare properties or methods."} +var Declaration_emit_elides_private_members_but_0_refers_to_a_private_member_Write_an_explicit_type_here = &Message{code: 7080, category: CategoryError, key: "Declaration_emit_elides_private_members_but_0_refers_to_a_private_member_Write_an_explicit_type_here_7080", text: "Declaration emit elides private members, but '{0}' refers to a private member. Write an explicit type here."} + var You_cannot_rename_this_element = &Message{code: 8000, category: CategoryError, key: "You_cannot_rename_this_element_8000", text: "You cannot rename this element."} var You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library = &Message{code: 8001, category: CategoryError, key: "You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library_8001", text: "You cannot rename elements that are defined in the standard TypeScript library."} @@ -7778,6 +7780,8 @@ func keyToMessage(key Key) *Message { return This_syntax_is_reserved_in_files_with_the_mts_or_cts_extension_Add_a_trailing_comma_or_explicit_constraint case "A_mapped_type_may_not_declare_properties_or_methods_7061": return A_mapped_type_may_not_declare_properties_or_methods + case "Declaration_emit_elides_private_members_but_0_refers_to_a_private_member_Write_an_explicit_type_here_7080": + return Declaration_emit_elides_private_members_but_0_refers_to_a_private_member_Write_an_explicit_type_here case "You_cannot_rename_this_element_8000": return You_cannot_rename_this_element case "You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library_8001": diff --git a/internal/diagnostics/extraDiagnosticMessages.json b/internal/diagnostics/extraDiagnosticMessages.json index 0d898d53be7..779f6c00b87 100644 --- a/internal/diagnostics/extraDiagnosticMessages.json +++ b/internal/diagnostics/extraDiagnosticMessages.json @@ -91,6 +91,10 @@ "category": "Error", "code": 5002 }, + "Declaration emit elides private members, but '{0}' refers to a private member. Write an explicit type here.": { + "category": "Error", + "code": 7080 + }, "Binding elements with initializers can't be exported directly with --isolatedDeclarations.": { "category": "Error", "code": 9019 diff --git a/internal/parser/parser.go b/internal/parser/parser.go index f429d36252e..fb81588889b 100644 --- a/internal/parser/parser.go +++ b/internal/parser/parser.go @@ -281,7 +281,7 @@ func ParseIsolatedEntityName(text string) *ast.EntityName { defer putParser(p) p.initializeState(ast.SourceFileParseOptions{}, text, core.ScriptKindJS) p.nextToken() - entityName := p.parseEntityName(true, nil) + entityName := p.parseEntityName(true, false, nil) return core.IfElse(p.token == ast.KindEndOfFile && len(p.diagnostics) == 0, entityName, nil) } @@ -2350,7 +2350,7 @@ func (p *Parser) parseModuleReference() *ast.Node { if p.token == ast.KindRequireKeyword && p.lookAhead((*Parser).nextTokenIsOpenParen) { return p.parseExternalModuleReference() } - return p.parseEntityName(false /*allowReservedWords*/, nil /*diagnosticMessage*/) + return p.parseEntityName(false /*allowReservedWords*/, false /*allowPrivateName*/, nil /*diagnosticMessage*/) } func (p *Parser) parseExternalModuleReference() *ast.Node { @@ -2941,10 +2941,10 @@ func (p *Parser) parseTypeReference() *ast.Node { } func (p *Parser) parseEntityNameOfTypeReference() *ast.Node { - return p.parseEntityName(true /*allowReservedWords*/, diagnostics.Type_expected) + return p.parseEntityName(true /*allowReservedWords*/, false /*allowPrivateName*/, diagnostics.Type_expected) } -func (p *Parser) parseEntityName(allowReservedWords bool, diagnosticMessage *diagnostics.Message) *ast.Node { +func (p *Parser) parseEntityName(allowReservedWords bool, allowPrivateName bool, diagnosticMessage *diagnostics.Message) *ast.Node { pos := p.nodePos() var entity *ast.Node if allowReservedWords { @@ -2958,7 +2958,7 @@ func (p *Parser) parseEntityName(allowReservedWords bool, diagnosticMessage *dia // `typeArguments` to report it as a grammar error in the checker. break } - entity = p.finishNode(p.factory.NewQualifiedName(entity, p.parseRightSideOfDot(allowReservedWords, false /*allowPrivateIdentifiers*/, true /*allowUnicodeEscapeSequenceInIdentifierName*/)), pos) + entity = p.finishNode(p.factory.NewQualifiedName(entity, p.parseRightSideOfDot(allowReservedWords, allowPrivateName, true /*allowUnicodeEscapeSequenceInIdentifierName*/)), pos) } return entity } @@ -3157,7 +3157,7 @@ func (p *Parser) parseImportAttributes(token ast.Kind, skipKeyword bool) *ast.No func (p *Parser) parseTypeQuery() *ast.Node { pos := p.nodePos() p.parseExpected(ast.KindTypeOfKeyword) - entityName := p.parseEntityName(true /*allowReservedWords*/, nil) + entityName := p.parseEntityName(true /*allowReservedWords*/, true /*allowPrivateName*/, nil) // Make sure we perform ASI to prevent parsing the next line's type arguments as part of an instantiation expression var typeArguments *ast.NodeList if !p.hasPrecedingLineBreak() { diff --git a/internal/printer/printer.go b/internal/printer/printer.go index 8d30695ffeb..82d3a2e41ce 100644 --- a/internal/printer/printer.go +++ b/internal/printer/printer.go @@ -1196,7 +1196,7 @@ func (p *Printer) emitQualifiedName(node *ast.QualifiedName) { state := p.enterNode(node.AsNode()) p.emitEntityName(node.Left) p.writePunctuation(".") - p.emitIdentifierName(node.Right.AsIdentifier()) + p.emitMemberName(node.Right) p.exitNode(node.AsNode(), state) } diff --git a/internal/transformers/declarations/transform.go b/internal/transformers/declarations/transform.go index 65ea3ed6f09..b89b96471d9 100644 --- a/internal/transformers/declarations/transform.go +++ b/internal/transformers/declarations/transform.go @@ -665,6 +665,11 @@ func (tx *DeclarationTransformer) visitDeclarationSubtree(input *ast.Node) *ast. case ast.KindTypeQuery: tx.checkEntityNameVisibility(input.AsTypeQueryNode().ExprName, tx.enclosingDeclaration) result = tx.Visitor().VisitEachChild(input) + case ast.KindQualifiedName: + if input.AsQualifiedName().Right.Kind == ast.KindPrivateIdentifier { + tx.state.addDiagnostic(createDiagnosticForNode(input, diagnostics.Declaration_emit_elides_private_members_but_0_refers_to_a_private_member_Write_an_explicit_type_here, input.AsQualifiedName().Right.Text())) + } + result = tx.Visitor().VisitEachChild(input) case ast.KindTupleType: result = tx.Visitor().VisitEachChild(input) if result != nil { diff --git a/testdata/baselines/reference/compiler/declarationEmitPrivateNameInTypeQuery.errors.txt b/testdata/baselines/reference/compiler/declarationEmitPrivateNameInTypeQuery.errors.txt new file mode 100644 index 00000000000..bda2506bb72 --- /dev/null +++ b/testdata/baselines/reference/compiler/declarationEmitPrivateNameInTypeQuery.errors.txt @@ -0,0 +1,50 @@ +declarationEmitPrivateNameInTypeQuery.ts(16,15): error TS7080: Declaration emit elides private members, but '#a' refers to a private member. Write an explicit type here. +declarationEmitPrivateNameInTypeQuery.ts(31,26): error TS7080: Declaration emit elides private members, but '#b' refers to a private member. Write an explicit type here. + + +==== declarationEmitPrivateNameInTypeQuery.ts (2 errors) ==== + export class C1 { + #a = 1; + + static #b = ""; + + #c() { + return 1 as const; + } + + get #d() { + return new Date(); + } + + ["#a"] = true; + + a: typeof this.#a = 1; + ~~~~~~~ +!!! error TS7080: Declaration emit elides private members, but '#a' refers to a private member. Write an explicit type here. + + test1(a: C1) { + const b: typeof a.#a = 1; + const c: typeof C1.#b = ""; + + return [b, c] as const; + } + + } + + export class C2 { + #a = 1; + + static #b = ""; + public prop!: typeof C2.#b; + ~~~~~ +!!! error TS7080: Declaration emit elides private members, but '#b' refers to a private member. Write an explicit type here. + + test1() { + class C { + test1(a: C2): typeof a.#a { + return 1; + } + } + return new C().test1(this); + } + } \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/declarationEmitPrivateNameInTypeQuery.js b/testdata/baselines/reference/compiler/declarationEmitPrivateNameInTypeQuery.js new file mode 100644 index 00000000000..9bce8312de0 --- /dev/null +++ b/testdata/baselines/reference/compiler/declarationEmitPrivateNameInTypeQuery.js @@ -0,0 +1,76 @@ +//// [tests/cases/compiler/declarationEmitPrivateNameInTypeQuery.ts] //// + +//// [declarationEmitPrivateNameInTypeQuery.ts] +export class C1 { + #a = 1; + + static #b = ""; + + #c() { + return 1 as const; + } + + get #d() { + return new Date(); + } + + ["#a"] = true; + + a: typeof this.#a = 1; + + test1(a: C1) { + const b: typeof a.#a = 1; + const c: typeof C1.#b = ""; + + return [b, c] as const; + } + +} + +export class C2 { + #a = 1; + + static #b = ""; + public prop!: typeof C2.#b; + + test1() { + class C { + test1(a: C2): typeof a.#a { + return 1; + } + } + return new C().test1(this); + } +} + +//// [declarationEmitPrivateNameInTypeQuery.js] +export class C1 { + #a = 1; + static #b = ""; + #c() { + return 1; + } + get #d() { + return new Date(); + } + ["#a"] = true; + a = 1; + test1(a) { + const b = 1; + const c = ""; + return [b, c]; + } +} +export class C2 { + #a = 1; + static #b = ""; + prop; + test1() { + class C { + test1(a) { + return 1; + } + } + return new C().test1(this); + } +} diff --git a/testdata/baselines/reference/compiler/declarationEmitPrivateNameInTypeQuery.symbols b/testdata/baselines/reference/compiler/declarationEmitPrivateNameInTypeQuery.symbols new file mode 100644 index 00000000000..13aeca18fe1 --- /dev/null +++ b/testdata/baselines/reference/compiler/declarationEmitPrivateNameInTypeQuery.symbols @@ -0,0 +1,95 @@ +//// [tests/cases/compiler/declarationEmitPrivateNameInTypeQuery.ts] //// + +=== declarationEmitPrivateNameInTypeQuery.ts === +export class C1 { +>C1 : Symbol(C1, Decl(declarationEmitPrivateNameInTypeQuery.ts, 0, 0)) + + #a = 1; +>#a : Symbol(C1.#a, Decl(declarationEmitPrivateNameInTypeQuery.ts, 0, 17)) + + static #b = ""; +>#b : Symbol(C1.#b, Decl(declarationEmitPrivateNameInTypeQuery.ts, 1, 11)) + + #c() { +>#c : Symbol(C1.#c, Decl(declarationEmitPrivateNameInTypeQuery.ts, 3, 19)) + + return 1 as const; +>const : Symbol(const) + } + + get #d() { +>#d : Symbol(C1.#d, Decl(declarationEmitPrivateNameInTypeQuery.ts, 7, 5)) + + return new Date(); +>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 2 more) + } + + ["#a"] = true; +>["#a"] : Symbol(C1["#a"], Decl(declarationEmitPrivateNameInTypeQuery.ts, 11, 5)) +>"#a" : Symbol(C1["#a"], Decl(declarationEmitPrivateNameInTypeQuery.ts, 11, 5)) + + a: typeof this.#a = 1; +>a : Symbol(C1.a, Decl(declarationEmitPrivateNameInTypeQuery.ts, 13, 18)) +>this.#a : Symbol(C1.#a, Decl(declarationEmitPrivateNameInTypeQuery.ts, 0, 17)) +>this : Symbol(C1, Decl(declarationEmitPrivateNameInTypeQuery.ts, 0, 0)) + + test1(a: C1) { +>test1 : Symbol(C1.test1, Decl(declarationEmitPrivateNameInTypeQuery.ts, 15, 26)) +>a : Symbol(a, Decl(declarationEmitPrivateNameInTypeQuery.ts, 17, 10)) +>C1 : Symbol(C1, Decl(declarationEmitPrivateNameInTypeQuery.ts, 0, 0)) + + const b: typeof a.#a = 1; +>b : Symbol(b, Decl(declarationEmitPrivateNameInTypeQuery.ts, 18, 13)) +>a.#a : Symbol(C1.#a, Decl(declarationEmitPrivateNameInTypeQuery.ts, 0, 17)) +>a : Symbol(a, Decl(declarationEmitPrivateNameInTypeQuery.ts, 17, 10)) + + const c: typeof C1.#b = ""; +>c : Symbol(c, Decl(declarationEmitPrivateNameInTypeQuery.ts, 19, 13)) +>C1.#b : Symbol(C1.#b, Decl(declarationEmitPrivateNameInTypeQuery.ts, 1, 11)) +>C1 : Symbol(C1, Decl(declarationEmitPrivateNameInTypeQuery.ts, 0, 0)) + + return [b, c] as const; +>b : Symbol(b, Decl(declarationEmitPrivateNameInTypeQuery.ts, 18, 13)) +>c : Symbol(c, Decl(declarationEmitPrivateNameInTypeQuery.ts, 19, 13)) +>const : Symbol(const) + } + +} + +export class C2 { +>C2 : Symbol(C2, Decl(declarationEmitPrivateNameInTypeQuery.ts, 24, 1)) + + #a = 1; +>#a : Symbol(C2.#a, Decl(declarationEmitPrivateNameInTypeQuery.ts, 26, 17)) + + static #b = ""; +>#b : Symbol(C2.#b, Decl(declarationEmitPrivateNameInTypeQuery.ts, 27, 11)) + + public prop!: typeof C2.#b; +>prop : Symbol(C2.prop, Decl(declarationEmitPrivateNameInTypeQuery.ts, 29, 19)) +>C2.#b : Symbol(C2.#b, Decl(declarationEmitPrivateNameInTypeQuery.ts, 27, 11)) +>C2 : Symbol(C2, Decl(declarationEmitPrivateNameInTypeQuery.ts, 24, 1)) + + test1() { +>test1 : Symbol(C2.test1, Decl(declarationEmitPrivateNameInTypeQuery.ts, 30, 31)) + + class C { +>C : Symbol(C, Decl(declarationEmitPrivateNameInTypeQuery.ts, 32, 13)) + + test1(a: C2): typeof a.#a { +>test1 : Symbol(C.test1, Decl(declarationEmitPrivateNameInTypeQuery.ts, 33, 17)) +>a : Symbol(a, Decl(declarationEmitPrivateNameInTypeQuery.ts, 34, 18)) +>C2 : Symbol(C2, Decl(declarationEmitPrivateNameInTypeQuery.ts, 24, 1)) +>a.#a : Symbol(C2.#a, Decl(declarationEmitPrivateNameInTypeQuery.ts, 26, 17)) +>a : Symbol(a, Decl(declarationEmitPrivateNameInTypeQuery.ts, 34, 18)) + + return 1; + } + } + return new C().test1(this); +>new C().test1 : Symbol(C.test1, Decl(declarationEmitPrivateNameInTypeQuery.ts, 33, 17)) +>C : Symbol(C, Decl(declarationEmitPrivateNameInTypeQuery.ts, 32, 13)) +>test1 : Symbol(C.test1, Decl(declarationEmitPrivateNameInTypeQuery.ts, 33, 17)) +>this : Symbol(C2, Decl(declarationEmitPrivateNameInTypeQuery.ts, 24, 1)) + } +} diff --git a/testdata/baselines/reference/compiler/declarationEmitPrivateNameInTypeQuery.types b/testdata/baselines/reference/compiler/declarationEmitPrivateNameInTypeQuery.types new file mode 100644 index 00000000000..d9dbb76f376 --- /dev/null +++ b/testdata/baselines/reference/compiler/declarationEmitPrivateNameInTypeQuery.types @@ -0,0 +1,107 @@ +//// [tests/cases/compiler/declarationEmitPrivateNameInTypeQuery.ts] //// + +=== declarationEmitPrivateNameInTypeQuery.ts === +export class C1 { +>C1 : C1 + + #a = 1; +>#a : number +>1 : 1 + + static #b = ""; +>#b : string +>"" : "" + + #c() { +>#c : () => 1 + + return 1 as const; +>1 as const : 1 +>1 : 1 + } + + get #d() { +>#d : Date + + return new Date(); +>new Date() : Date +>Date : DateConstructor + } + + ["#a"] = true; +>["#a"] : boolean +>"#a" : "#a" +>true : true + + a: typeof this.#a = 1; +>a : number +>this.#a : number +>this : this +>1 : 1 + + test1(a: C1) { +>test1 : (a: C1) => readonly [number, string] +>a : C1 + + const b: typeof a.#a = 1; +>b : number +>a.#a : number +>a : C1 +>1 : 1 + + const c: typeof C1.#b = ""; +>c : string +>C1.#b : string +>C1 : typeof C1 +>"" : "" + + return [b, c] as const; +>[b, c] as const : readonly [number, string] +>[b, c] : readonly [number, string] +>b : number +>c : string + } + +} + +export class C2 { +>C2 : C2 + + #a = 1; +>#a : number +>1 : 1 + + static #b = ""; +>#b : string +>"" : "" + + public prop!: typeof C2.#b; +>prop : string +>C2.#b : string +>C2 : typeof C2 + + test1() { +>test1 : () => number + + class C { +>C : C + + test1(a: C2): typeof a.#a { +>test1 : (a: C2) => typeof a.#a +>a : C2 +>a.#a : number +>a : C2 + + return 1; +>1 : 1 + } + } + return new C().test1(this); +>new C().test1(this) : number +>new C().test1 : (a: C2) => typeof a.#a +>new C() : C +>C : typeof C +>test1 : (a: C2) => typeof a.#a +>this : this + } +} diff --git a/testdata/baselines/reference/compiler/privateNameInTypeQuery.errors.txt b/testdata/baselines/reference/compiler/privateNameInTypeQuery.errors.txt new file mode 100644 index 00000000000..73d8e511388 --- /dev/null +++ b/testdata/baselines/reference/compiler/privateNameInTypeQuery.errors.txt @@ -0,0 +1,78 @@ +privateNameInTypeQuery.ts(6,5): error TS6133: '#c' is declared but its value is never read. +privateNameInTypeQuery.ts(10,9): error TS6133: '#d' is declared but its value is never read. +privateNameInTypeQuery.ts(16,15): error TS7080: Declaration emit elides private members, but '#a' refers to a private member. Write an explicit type here. +privateNameInTypeQuery.ts(22,28): error TS2339: Property '#a' does not exist on type 'typeof C1'. +privateNameInTypeQuery.ts(28,39): error TS7080: Declaration emit elides private members, but '#a' refers to a private member. Write an explicit type here. +privateNameInTypeQuery.ts(33,51): error TS7080: Declaration emit elides private members, but '#a' refers to a private member. Write an explicit type here. +privateNameInTypeQuery.ts(37,14): error TS2693: 'any' only refers to a type, but is being used as a value here. +privateNameInTypeQuery.ts(37,20): error TS1003: Identifier expected. +privateNameInTypeQuery.ts(41,14): error TS2693: 'never' only refers to a type, but is being used as a value here. +privateNameInTypeQuery.ts(41,22): error TS1003: Identifier expected. + + +==== privateNameInTypeQuery.ts (10 errors) ==== + export class C1 { + #a = 1; + + static #b = ""; + + #c() { + ~~ +!!! error TS6133: '#c' is declared but its value is never read. + return 1 as const; + } + + get #d() { + ~~ +!!! error TS6133: '#d' is declared but its value is never read. + return new Date(); + } + + ["#a"] = true; + + a: typeof this.#a = 1; + ~~~~~~~ +!!! error TS7080: Declaration emit elides private members, but '#a' refers to a private member. Write an explicit type here. + + test1(a: C1) { + const b: typeof a.#a = 1; + const c: typeof C1.#b = ""; + + type D = typeof C1.#a; + ~~ +!!! error TS2339: Property '#a' does not exist on type 'typeof C1'. + var d: D = 1; + + return [b, c, d] as const; + } + + test2(a: T): typeof a.#a { + ~~~~ +!!! error TS7080: Declaration emit elides private members, but '#a' refers to a private member. Write an explicit type here. + const b: typeof a.#a = a.#a; + return b; + } + + test3(): typeof this.#a { + ~~~~~~~ +!!! error TS7080: Declaration emit elides private members, but '#a' refers to a private member. Write an explicit type here. + return undefined as any; + } + + test4(): any.#a { + ~~~ +!!! error TS2693: 'any' only refers to a type, but is being used as a value here. + +!!! error TS1003: Identifier expected. + return ""; + } + + test5(): never.#a { + ~~~~~ +!!! error TS2693: 'never' only refers to a type, but is being used as a value here. + +!!! error TS1003: Identifier expected. + throw new Error(); + } + } + \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/privateNameInTypeQuery.js b/testdata/baselines/reference/compiler/privateNameInTypeQuery.js new file mode 100644 index 00000000000..6e2a3682c39 --- /dev/null +++ b/testdata/baselines/reference/compiler/privateNameInTypeQuery.js @@ -0,0 +1,81 @@ +//// [tests/cases/compiler/privateNameInTypeQuery.ts] //// + +//// [privateNameInTypeQuery.ts] +export class C1 { + #a = 1; + + static #b = ""; + + #c() { + return 1 as const; + } + + get #d() { + return new Date(); + } + + ["#a"] = true; + + a: typeof this.#a = 1; + + test1(a: C1) { + const b: typeof a.#a = 1; + const c: typeof C1.#b = ""; + + type D = typeof C1.#a; + var d: D = 1; + + return [b, c, d] as const; + } + + test2(a: T): typeof a.#a { + const b: typeof a.#a = a.#a; + return b; + } + + test3(): typeof this.#a { + return undefined as any; + } + + test4(): any.#a { + return ""; + } + + test5(): never.#a { + throw new Error(); + } +} + + +//// [privateNameInTypeQuery.js] +export class C1 { + #a = 1; + static #b = ""; + #c() { + return 1; + } + get #d() { + return new Date(); + } + ["#a"] = true; + a = 1; + test1(a) { + const b = 1; + const c = ""; + var d = 1; + return [b, c, d]; + } + test2(a) { + const b = a.#a; + return b; + } + test3() { + return undefined; + } + test4() { + return ""; + } + test5() { + throw new Error(); + } +} diff --git a/testdata/baselines/reference/compiler/privateNameInTypeQuery.symbols b/testdata/baselines/reference/compiler/privateNameInTypeQuery.symbols new file mode 100644 index 00000000000..2702d1c87be --- /dev/null +++ b/testdata/baselines/reference/compiler/privateNameInTypeQuery.symbols @@ -0,0 +1,115 @@ +//// [tests/cases/compiler/privateNameInTypeQuery.ts] //// + +=== privateNameInTypeQuery.ts === +export class C1 { +>C1 : Symbol(C1, Decl(privateNameInTypeQuery.ts, 0, 0)) + + #a = 1; +>#a : Symbol(C1.#a, Decl(privateNameInTypeQuery.ts, 0, 17)) + + static #b = ""; +>#b : Symbol(C1.#b, Decl(privateNameInTypeQuery.ts, 1, 11)) + + #c() { +>#c : Symbol(C1.#c, Decl(privateNameInTypeQuery.ts, 3, 19)) + + return 1 as const; +>const : Symbol(const) + } + + get #d() { +>#d : Symbol(C1.#d, Decl(privateNameInTypeQuery.ts, 7, 5)) + + return new Date(); +>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 2 more) + } + + ["#a"] = true; +>["#a"] : Symbol(C1["#a"], Decl(privateNameInTypeQuery.ts, 11, 5)) +>"#a" : Symbol(C1["#a"], Decl(privateNameInTypeQuery.ts, 11, 5)) + + a: typeof this.#a = 1; +>a : Symbol(C1.a, Decl(privateNameInTypeQuery.ts, 13, 18)) +>this.#a : Symbol(C1.#a, Decl(privateNameInTypeQuery.ts, 0, 17)) +>this : Symbol(C1, Decl(privateNameInTypeQuery.ts, 0, 0)) + + test1(a: C1) { +>test1 : Symbol(C1.test1, Decl(privateNameInTypeQuery.ts, 15, 26)) +>a : Symbol(a, Decl(privateNameInTypeQuery.ts, 17, 10)) +>C1 : Symbol(C1, Decl(privateNameInTypeQuery.ts, 0, 0)) + + const b: typeof a.#a = 1; +>b : Symbol(b, Decl(privateNameInTypeQuery.ts, 18, 13)) +>a.#a : Symbol(C1.#a, Decl(privateNameInTypeQuery.ts, 0, 17)) +>a : Symbol(a, Decl(privateNameInTypeQuery.ts, 17, 10)) + + const c: typeof C1.#b = ""; +>c : Symbol(c, Decl(privateNameInTypeQuery.ts, 19, 13)) +>C1.#b : Symbol(C1.#b, Decl(privateNameInTypeQuery.ts, 1, 11)) +>C1 : Symbol(C1, Decl(privateNameInTypeQuery.ts, 0, 0)) + + type D = typeof C1.#a; +>D : Symbol(D, Decl(privateNameInTypeQuery.ts, 19, 35)) +>C1 : Symbol(C1, Decl(privateNameInTypeQuery.ts, 0, 0)) + + var d: D = 1; +>d : Symbol(d, Decl(privateNameInTypeQuery.ts, 22, 11)) +>D : Symbol(D, Decl(privateNameInTypeQuery.ts, 19, 35)) + + return [b, c, d] as const; +>b : Symbol(b, Decl(privateNameInTypeQuery.ts, 18, 13)) +>c : Symbol(c, Decl(privateNameInTypeQuery.ts, 19, 13)) +>d : Symbol(d, Decl(privateNameInTypeQuery.ts, 22, 11)) +>const : Symbol(const) + } + + test2(a: T): typeof a.#a { +>test2 : Symbol(C1.test2, Decl(privateNameInTypeQuery.ts, 25, 5)) +>T : Symbol(T, Decl(privateNameInTypeQuery.ts, 27, 10)) +>C1 : Symbol(C1, Decl(privateNameInTypeQuery.ts, 0, 0)) +>a : Symbol(a, Decl(privateNameInTypeQuery.ts, 27, 24)) +>T : Symbol(T, Decl(privateNameInTypeQuery.ts, 27, 10)) +>a.#a : Symbol(C1.#a, Decl(privateNameInTypeQuery.ts, 0, 17)) +>a : Symbol(a, Decl(privateNameInTypeQuery.ts, 27, 24)) + + const b: typeof a.#a = a.#a; +>b : Symbol(b, Decl(privateNameInTypeQuery.ts, 28, 13)) +>a.#a : Symbol(C1.#a, Decl(privateNameInTypeQuery.ts, 0, 17)) +>a : Symbol(a, Decl(privateNameInTypeQuery.ts, 27, 24)) +>a.#a : Symbol(C1.#a, Decl(privateNameInTypeQuery.ts, 0, 17)) +>a : Symbol(a, Decl(privateNameInTypeQuery.ts, 27, 24)) + + return b; +>b : Symbol(b, Decl(privateNameInTypeQuery.ts, 28, 13)) + } + + test3(): typeof this.#a { +>test3 : Symbol(C1.test3, Decl(privateNameInTypeQuery.ts, 30, 5)) +>T : Symbol(T, Decl(privateNameInTypeQuery.ts, 32, 10)) +>C1 : Symbol(C1, Decl(privateNameInTypeQuery.ts, 0, 0)) +>a : Symbol(a, Decl(privateNameInTypeQuery.ts, 32, 26)) +>this.#a : Symbol(C1.#a, Decl(privateNameInTypeQuery.ts, 0, 17)) +>this : Symbol(C1, Decl(privateNameInTypeQuery.ts, 0, 0)) + + return undefined as any; +>undefined : Symbol(undefined) + } + + test4(): any.#a { +>test4 : Symbol(C1.test4, Decl(privateNameInTypeQuery.ts, 34, 5)) +>any : Symbol(any) +> : Symbol(unknown) + + return ""; + } + + test5(): never.#a { +>test5 : Symbol(C1.test5, Decl(privateNameInTypeQuery.ts, 38, 5)) +>never : Symbol(never) +> : Symbol(unknown) + + throw new Error(); +>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2022.error.d.ts, --, --)) + } +} + diff --git a/testdata/baselines/reference/compiler/privateNameInTypeQuery.types b/testdata/baselines/reference/compiler/privateNameInTypeQuery.types new file mode 100644 index 00000000000..272124132b9 --- /dev/null +++ b/testdata/baselines/reference/compiler/privateNameInTypeQuery.types @@ -0,0 +1,120 @@ +//// [tests/cases/compiler/privateNameInTypeQuery.ts] //// + +=== privateNameInTypeQuery.ts === +export class C1 { +>C1 : C1 + + #a = 1; +>#a : number +>1 : 1 + + static #b = ""; +>#b : string +>"" : "" + + #c() { +>#c : () => 1 + + return 1 as const; +>1 as const : 1 +>1 : 1 + } + + get #d() { +>#d : Date + + return new Date(); +>new Date() : Date +>Date : DateConstructor + } + + ["#a"] = true; +>["#a"] : boolean +>"#a" : "#a" +>true : true + + a: typeof this.#a = 1; +>a : number +>this.#a : number +>this : this +>1 : 1 + + test1(a: C1) { +>test1 : (a: C1) => readonly [number, string, any] +>a : C1 + + const b: typeof a.#a = 1; +>b : number +>a.#a : number +>a : C1 +>1 : 1 + + const c: typeof C1.#b = ""; +>c : string +>C1.#b : string +>C1 : typeof C1 +>"" : "" + + type D = typeof C1.#a; +>D : any +>C1.#a : any +>C1 : typeof C1 + + var d: D = 1; +>d : any +>1 : 1 + + return [b, c, d] as const; +>[b, c, d] as const : readonly [number, string, any] +>[b, c, d] : readonly [number, string, any] +>b : number +>c : string +>d : any + } + + test2(a: T): typeof a.#a { +>test2 : (a: T) => typeof a.#a +>a : T +>a.#a : number +>a : T + + const b: typeof a.#a = a.#a; +>b : number +>a.#a : number +>a : T +>a.#a : number +>a : T + + return b; +>b : number + } + + test3(): typeof this.#a { +>test3 : () => typeof this.#a +>a : string +>this.#a : number +>this : this + + return undefined as any; +>undefined as any : any +>undefined : undefined + } + + test4(): any.#a { +>test4 : () => any. +>any : any + + return ""; +>"" : "" + } + + test5(): never.#a { +>test5 : () => never. +>never : any + + throw new Error(); +>new Error() : Error +>Error : ErrorConstructor + } +} + diff --git a/testdata/tests/cases/compiler/declarationEmitPrivateNameInTypeQuery.ts b/testdata/tests/cases/compiler/declarationEmitPrivateNameInTypeQuery.ts new file mode 100644 index 00000000000..f3faa32a6d4 --- /dev/null +++ b/testdata/tests/cases/compiler/declarationEmitPrivateNameInTypeQuery.ts @@ -0,0 +1,45 @@ +// @declaration: true +// @strict: true +// @target: esnext + +export class C1 { + #a = 1; + + static #b = ""; + + #c() { + return 1 as const; + } + + get #d() { + return new Date(); + } + + ["#a"] = true; + + a: typeof this.#a = 1; + + test1(a: C1) { + const b: typeof a.#a = 1; + const c: typeof C1.#b = ""; + + return [b, c] as const; + } + +} + +export class C2 { + #a = 1; + + static #b = ""; + public prop!: typeof C2.#b; + + test1() { + class C { + test1(a: C2): typeof a.#a { + return 1; + } + } + return new C().test1(this); + } +} \ No newline at end of file diff --git a/testdata/tests/cases/compiler/privateNameInTypeQuery.ts b/testdata/tests/cases/compiler/privateNameInTypeQuery.ts new file mode 100644 index 00000000000..b4f6aa9edb8 --- /dev/null +++ b/testdata/tests/cases/compiler/privateNameInTypeQuery.ts @@ -0,0 +1,49 @@ +// @declaration: true +// @noUnusedLocals: true +// @strict: true +// @target: esnext + +export class C1 { + #a = 1; + + static #b = ""; + + #c() { + return 1 as const; + } + + get #d() { + return new Date(); + } + + ["#a"] = true; + + a: typeof this.#a = 1; + + test1(a: C1) { + const b: typeof a.#a = 1; + const c: typeof C1.#b = ""; + + type D = typeof C1.#a; + var d: D = 1; + + return [b, c, d] as const; + } + + test2(a: T): typeof a.#a { + const b: typeof a.#a = a.#a; + return b; + } + + test3(): typeof this.#a { + return undefined as any; + } + + test4(): any.#a { + return ""; + } + + test5(): never.#a { + throw new Error(); + } +}