Make function properties context-sensitive based on their return statements (#50903)

This commit is contained in:
Mateusz Burzyński 2023-03-20 21:53:16 +01:00 committed by GitHub
parent 4fcb8b8be6
commit acfb0b53d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 90 additions and 2 deletions

View File

@ -19114,8 +19114,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
function hasContextSensitiveReturnExpression(node: FunctionLikeDeclaration) {
// TODO(anhans): A block should be context-sensitive if it has a context-sensitive return value.
return !node.typeParameters && !getEffectiveReturnTypeNode(node) && !!node.body && node.body.kind !== SyntaxKind.Block && isContextSensitive(node.body);
if (node.typeParameters || getEffectiveReturnTypeNode(node) || !node.body) {
return false;
}
if (node.body.kind !== SyntaxKind.Block) {
return isContextSensitive(node.body);
}
return !!forEachReturnStatement(node.body as Block, (statement) => !!statement.expression && isContextSensitive(statement.expression));
}
function isContextSensitiveFunctionOrObjectLiteralMethod(func: Node): func is FunctionExpression | ArrowFunction | MethodDeclaration {

View File

@ -0,0 +1,32 @@
=== tests/cases/compiler/inferPropertyWithContextSensitiveReturnStatement.ts ===
// repro #50687
declare function repro<T>(config: {
>repro : Symbol(repro, Decl(inferPropertyWithContextSensitiveReturnStatement.ts, 0, 0))
>T : Symbol(T, Decl(inferPropertyWithContextSensitiveReturnStatement.ts, 2, 23))
>config : Symbol(config, Decl(inferPropertyWithContextSensitiveReturnStatement.ts, 2, 26))
params: T;
>params : Symbol(params, Decl(inferPropertyWithContextSensitiveReturnStatement.ts, 2, 35))
>T : Symbol(T, Decl(inferPropertyWithContextSensitiveReturnStatement.ts, 2, 23))
callback: () => (params: T) => number;
>callback : Symbol(callback, Decl(inferPropertyWithContextSensitiveReturnStatement.ts, 3, 12))
>params : Symbol(params, Decl(inferPropertyWithContextSensitiveReturnStatement.ts, 4, 19))
>T : Symbol(T, Decl(inferPropertyWithContextSensitiveReturnStatement.ts, 2, 23))
}): void;
repro({
>repro : Symbol(repro, Decl(inferPropertyWithContextSensitiveReturnStatement.ts, 0, 0))
params: 1,
>params : Symbol(params, Decl(inferPropertyWithContextSensitiveReturnStatement.ts, 7, 7))
callback: () => { return a => a + 1 },
>callback : Symbol(callback, Decl(inferPropertyWithContextSensitiveReturnStatement.ts, 8, 12))
>a : Symbol(a, Decl(inferPropertyWithContextSensitiveReturnStatement.ts, 9, 26))
>a : Symbol(a, Decl(inferPropertyWithContextSensitiveReturnStatement.ts, 9, 26))
});

View File

@ -0,0 +1,36 @@
=== tests/cases/compiler/inferPropertyWithContextSensitiveReturnStatement.ts ===
// repro #50687
declare function repro<T>(config: {
>repro : <T>(config: { params: T; callback: () => (params: T) => number; }) => void
>config : { params: T; callback: () => (params: T) => number; }
params: T;
>params : T
callback: () => (params: T) => number;
>callback : () => (params: T) => number
>params : T
}): void;
repro({
>repro({ params: 1, callback: () => { return a => a + 1 },}) : void
>repro : <T>(config: { params: T; callback: () => (params: T) => number; }) => void
>{ params: 1, callback: () => { return a => a + 1 },} : { params: number; callback: () => (a: number) => number; }
params: 1,
>params : number
>1 : 1
callback: () => { return a => a + 1 },
>callback : () => (a: number) => number
>() => { return a => a + 1 } : () => (a: number) => number
>a => a + 1 : (a: number) => number
>a : number
>a + 1 : number
>a : number
>1 : 1
});

View File

@ -0,0 +1,15 @@
// @noEmit: true
// @strict: true
// repro #50687
declare function repro<T>(config: {
params: T;
callback: () => (params: T) => number;
}): void;
repro({
params: 1,
callback: () => { return a => a + 1 },
});