mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 12:32:08 -06:00
Correctly resolve declared type for late bound property symbols of function expressions (#55357)
Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com>
This commit is contained in:
parent
0a87761521
commit
f834133fe2
@ -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());
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
Loading…
x
Reference in New Issue
Block a user