diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 781bf2217d847..52abf556af78e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5526,6 +5526,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getMergedSymbol(symbol.parent && getLateBoundSymbol(symbol.parent)); } + function getFunctionExpressionParentSymbolOrSymbol(symbol: Symbol) { + return symbol.valueDeclaration?.kind === SyntaxKind.ArrowFunction || symbol.valueDeclaration?.kind === SyntaxKind.FunctionExpression + ? getSymbolOfNode(symbol.valueDeclaration.parent) || symbol + : symbol; + } + function getAlternativeContainingModules(symbol: Symbol, enclosingDeclaration: Node): Symbol[] { const containingFile = getSourceFileOfNode(enclosingDeclaration); const id = getNodeId(containingFile); @@ -11236,11 +11242,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } if (symbol.parent?.valueDeclaration) { - const typeNode = getEffectiveTypeAnnotationNode(symbol.parent.valueDeclaration); - if (typeNode) { - const annotationSymbol = getPropertyOfType(getTypeFromTypeNode(typeNode), symbol.escapedName); - if (annotationSymbol) { - return getNonMissingTypeOfSymbol(annotationSymbol); + const possiblyAnnotatedSymbol = getFunctionExpressionParentSymbolOrSymbol(symbol.parent); + if (possiblyAnnotatedSymbol.valueDeclaration) { + const typeNode = getEffectiveTypeAnnotationNode(possiblyAnnotatedSymbol.valueDeclaration); + if (typeNode) { + const annotationSymbol = getPropertyOfType(getTypeFromTypeNode(typeNode), symbol.escapedName); + if (annotationSymbol) { + return getNonMissingTypeOfSymbol(annotationSymbol); + } } } } @@ -12932,9 +12941,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } } - const assignments = (symbol.valueDeclaration?.kind === SyntaxKind.ArrowFunction || symbol.valueDeclaration?.kind === SyntaxKind.FunctionExpression) && - getSymbolOfNode(symbol.valueDeclaration.parent)?.assignmentDeclarationMembers || - symbol.assignmentDeclarationMembers; + const assignments = getFunctionExpressionParentSymbolOrSymbol(symbol).assignmentDeclarationMembers; if (assignments) { const decls = arrayFrom(assignments.values()); diff --git a/tests/baselines/reference/expandoFunctionExpressionsWithDynamicNames2.symbols b/tests/baselines/reference/expandoFunctionExpressionsWithDynamicNames2.symbols new file mode 100644 index 0000000000000..a5f7446fd70bd --- /dev/null +++ b/tests/baselines/reference/expandoFunctionExpressionsWithDynamicNames2.symbols @@ -0,0 +1,42 @@ +//// [tests/cases/compiler/expandoFunctionExpressionsWithDynamicNames2.ts] //// + +=== expandoFunctionExpressionsWithDynamicNames2.ts === +const mySymbol = Symbol(); +>mySymbol : Symbol(mySymbol, Decl(expandoFunctionExpressionsWithDynamicNames2.ts, 0, 5)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) + +interface Foo { +>Foo : Symbol(Foo, Decl(expandoFunctionExpressionsWithDynamicNames2.ts, 0, 26)) + + (): void; + [mySymbol]: true; +>[mySymbol] : Symbol(Foo[mySymbol], Decl(expandoFunctionExpressionsWithDynamicNames2.ts, 2, 11)) +>mySymbol : Symbol(mySymbol, Decl(expandoFunctionExpressionsWithDynamicNames2.ts, 0, 5)) +} +const foo: Foo = () => {}; +>foo : Symbol(foo, Decl(expandoFunctionExpressionsWithDynamicNames2.ts, 5, 5), Decl(expandoFunctionExpressionsWithDynamicNames2.ts, 5, 26)) +>Foo : Symbol(Foo, Decl(expandoFunctionExpressionsWithDynamicNames2.ts, 0, 26)) + +foo[mySymbol] = true; +>foo : Symbol(foo, Decl(expandoFunctionExpressionsWithDynamicNames2.ts, 5, 5), Decl(expandoFunctionExpressionsWithDynamicNames2.ts, 5, 26)) +>mySymbol : Symbol(mySymbol, Decl(expandoFunctionExpressionsWithDynamicNames2.ts, 0, 5)) + +interface Bar { +>Bar : Symbol(Bar, Decl(expandoFunctionExpressionsWithDynamicNames2.ts, 6, 21)) + + (): void; + test: true; +>test : Symbol(Bar.test, Decl(expandoFunctionExpressionsWithDynamicNames2.ts, 9, 11)) +} +const t = "test" as const; +>t : Symbol(t, Decl(expandoFunctionExpressionsWithDynamicNames2.ts, 12, 5)) +>const : Symbol(const) + +const bar: Bar = () => {}; +>bar : Symbol(bar, Decl(expandoFunctionExpressionsWithDynamicNames2.ts, 13, 5), Decl(expandoFunctionExpressionsWithDynamicNames2.ts, 13, 26)) +>Bar : Symbol(Bar, Decl(expandoFunctionExpressionsWithDynamicNames2.ts, 6, 21)) + +bar[t] = true; +>bar : Symbol(bar, Decl(expandoFunctionExpressionsWithDynamicNames2.ts, 13, 5), Decl(expandoFunctionExpressionsWithDynamicNames2.ts, 13, 26)) +>t : Symbol(t, Decl(expandoFunctionExpressionsWithDynamicNames2.ts, 12, 5)) + diff --git a/tests/baselines/reference/expandoFunctionExpressionsWithDynamicNames2.types b/tests/baselines/reference/expandoFunctionExpressionsWithDynamicNames2.types new file mode 100644 index 0000000000000..0aedacb4d9efc --- /dev/null +++ b/tests/baselines/reference/expandoFunctionExpressionsWithDynamicNames2.types @@ -0,0 +1,48 @@ +//// [tests/cases/compiler/expandoFunctionExpressionsWithDynamicNames2.ts] //// + +=== expandoFunctionExpressionsWithDynamicNames2.ts === +const mySymbol = Symbol(); +>mySymbol : unique symbol +>Symbol() : unique symbol +>Symbol : SymbolConstructor + +interface Foo { + (): void; + [mySymbol]: true; +>[mySymbol] : true +>mySymbol : unique symbol +>true : true +} +const foo: Foo = () => {}; +>foo : Foo +>() => {} : { (): void; [mySymbol]: true; } + +foo[mySymbol] = true; +>foo[mySymbol] = true : true +>foo[mySymbol] : true +>foo : Foo +>mySymbol : unique symbol +>true : true + +interface Bar { + (): void; + test: true; +>test : true +>true : true +} +const t = "test" as const; +>t : "test" +>"test" as const : "test" +>"test" : "test" + +const bar: Bar = () => {}; +>bar : Bar +>() => {} : { (): void; test: true; } + +bar[t] = true; +>bar[t] = true : true +>bar[t] : true +>bar : Bar +>t : "test" +>true : true + diff --git a/tests/cases/compiler/expandoFunctionExpressionsWithDynamicNames2.ts b/tests/cases/compiler/expandoFunctionExpressionsWithDynamicNames2.ts new file mode 100644 index 0000000000000..86be30e27a216 --- /dev/null +++ b/tests/cases/compiler/expandoFunctionExpressionsWithDynamicNames2.ts @@ -0,0 +1,19 @@ +// @strict: true +// @lib: esnext +// @noEmit: true + +const mySymbol = Symbol(); +interface Foo { + (): void; + [mySymbol]: true; +} +const foo: Foo = () => {}; +foo[mySymbol] = true; + +interface Bar { + (): void; + test: true; +} +const t = "test" as const; +const bar: Bar = () => {}; +bar[t] = true; \ No newline at end of file