mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Exclude parameters of non-inferrable signatures from inference (#53756)
This commit is contained in:
parent
b92483f20c
commit
e49db97f97
@ -25026,12 +25026,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
|
||||
function inferFromSignature(source: Signature, target: Signature) {
|
||||
const saveBivariant = bivariant;
|
||||
const kind = target.declaration ? target.declaration.kind : SyntaxKind.Unknown;
|
||||
// Once we descend into a bivariant signature we remain bivariant for all nested inferences
|
||||
bivariant = bivariant || kind === SyntaxKind.MethodDeclaration || kind === SyntaxKind.MethodSignature || kind === SyntaxKind.Constructor;
|
||||
applyToParameterTypes(source, target, inferFromContravariantTypesIfStrictFunctionTypes);
|
||||
bivariant = saveBivariant;
|
||||
if (!(source.flags & SignatureFlags.IsNonInferrable)) {
|
||||
const saveBivariant = bivariant;
|
||||
const kind = target.declaration ? target.declaration.kind : SyntaxKind.Unknown;
|
||||
// Once we descend into a bivariant signature we remain bivariant for all nested inferences
|
||||
bivariant = bivariant || kind === SyntaxKind.MethodDeclaration || kind === SyntaxKind.MethodSignature || kind === SyntaxKind.Constructor;
|
||||
applyToParameterTypes(source, target, inferFromContravariantTypesIfStrictFunctionTypes);
|
||||
bivariant = saveBivariant;
|
||||
}
|
||||
applyToReturnTypes(source, target, inferFromTypes);
|
||||
}
|
||||
|
||||
@ -35783,7 +35785,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return links.contextFreeType;
|
||||
}
|
||||
const returnType = getReturnTypeFromBody(node, checkMode);
|
||||
const returnOnlySignature = createSignature(/*declaration*/ undefined, /*typeParameters*/ undefined, /*thisParameter*/ undefined, emptyArray, returnType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None);
|
||||
const returnOnlySignature = createSignature(/*declaration*/ undefined, /*typeParameters*/ undefined, /*thisParameter*/ undefined, emptyArray, returnType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.IsNonInferrable);
|
||||
const returnOnlyType = createAnonymousType(node.symbol, emptySymbols, [returnOnlySignature], emptyArray, emptyArray);
|
||||
returnOnlyType.objectFlags |= ObjectFlags.NonInferrableType;
|
||||
return links.contextFreeType = returnOnlyType;
|
||||
|
||||
@ -6704,6 +6704,7 @@ export const enum SignatureFlags {
|
||||
IsInnerCallChain = 1 << 3, // Indicates signature comes from a CallChain nested in an outer OptionalChain
|
||||
IsOuterCallChain = 1 << 4, // Indicates signature comes from a CallChain that is the outermost chain of an optional expression
|
||||
IsUntypedSignatureInJSFile = 1 << 5, // Indicates signature is from a js file and has no types
|
||||
IsNonInferrable = 1 << 6, // Indicates signature comes from a non-inferrable type
|
||||
|
||||
// We do not propagate `IsInnerCallChain` or `IsOuterCallChain` to instantiated signatures, as that would result in us
|
||||
// attempting to add `| undefined` on each recursive call to `getReturnTypeOfSignature` when
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
=== tests/cases/compiler/nonInferrableTypePropagation3.ts ===
|
||||
// Repro from #53748
|
||||
|
||||
declare type Callback<Args extends any[], Out, R> = (...args: Args) => (data: Out) => R;
|
||||
>Callback : Symbol(Callback, Decl(nonInferrableTypePropagation3.ts, 0, 0))
|
||||
>Args : Symbol(Args, Decl(nonInferrableTypePropagation3.ts, 2, 22))
|
||||
>Out : Symbol(Out, Decl(nonInferrableTypePropagation3.ts, 2, 41))
|
||||
>R : Symbol(R, Decl(nonInferrableTypePropagation3.ts, 2, 46))
|
||||
>args : Symbol(args, Decl(nonInferrableTypePropagation3.ts, 2, 53))
|
||||
>Args : Symbol(Args, Decl(nonInferrableTypePropagation3.ts, 2, 22))
|
||||
>data : Symbol(data, Decl(nonInferrableTypePropagation3.ts, 2, 72))
|
||||
>Out : Symbol(Out, Decl(nonInferrableTypePropagation3.ts, 2, 41))
|
||||
>R : Symbol(R, Decl(nonInferrableTypePropagation3.ts, 2, 46))
|
||||
|
||||
declare function factory<Out>(): <Args extends any[], R>(callback: Callback<Args, Out, R>) => (...args: Args) => R;
|
||||
>factory : Symbol(factory, Decl(nonInferrableTypePropagation3.ts, 2, 88))
|
||||
>Out : Symbol(Out, Decl(nonInferrableTypePropagation3.ts, 3, 25))
|
||||
>Args : Symbol(Args, Decl(nonInferrableTypePropagation3.ts, 3, 34))
|
||||
>R : Symbol(R, Decl(nonInferrableTypePropagation3.ts, 3, 53))
|
||||
>callback : Symbol(callback, Decl(nonInferrableTypePropagation3.ts, 3, 57))
|
||||
>Callback : Symbol(Callback, Decl(nonInferrableTypePropagation3.ts, 0, 0))
|
||||
>Args : Symbol(Args, Decl(nonInferrableTypePropagation3.ts, 3, 34))
|
||||
>Out : Symbol(Out, Decl(nonInferrableTypePropagation3.ts, 3, 25))
|
||||
>R : Symbol(R, Decl(nonInferrableTypePropagation3.ts, 3, 53))
|
||||
>args : Symbol(args, Decl(nonInferrableTypePropagation3.ts, 3, 95))
|
||||
>Args : Symbol(Args, Decl(nonInferrableTypePropagation3.ts, 3, 34))
|
||||
>R : Symbol(R, Decl(nonInferrableTypePropagation3.ts, 3, 53))
|
||||
|
||||
const make = factory<{id: string, age: number}[]>();
|
||||
>make : Symbol(make, Decl(nonInferrableTypePropagation3.ts, 5, 5))
|
||||
>factory : Symbol(factory, Decl(nonInferrableTypePropagation3.ts, 2, 88))
|
||||
>id : Symbol(id, Decl(nonInferrableTypePropagation3.ts, 5, 22))
|
||||
>age : Symbol(age, Decl(nonInferrableTypePropagation3.ts, 5, 33))
|
||||
|
||||
const usersOverAge = make((age: number) => data => {
|
||||
>usersOverAge : Symbol(usersOverAge, Decl(nonInferrableTypePropagation3.ts, 7, 5))
|
||||
>make : Symbol(make, Decl(nonInferrableTypePropagation3.ts, 5, 5))
|
||||
>age : Symbol(age, Decl(nonInferrableTypePropagation3.ts, 7, 27))
|
||||
>data : Symbol(data, Decl(nonInferrableTypePropagation3.ts, 7, 42))
|
||||
|
||||
return data.filter(user => user.age >= age);
|
||||
>data.filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>data : Symbol(data, Decl(nonInferrableTypePropagation3.ts, 7, 42))
|
||||
>filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>user : Symbol(user, Decl(nonInferrableTypePropagation3.ts, 8, 23))
|
||||
>user.age : Symbol(age, Decl(nonInferrableTypePropagation3.ts, 5, 33))
|
||||
>user : Symbol(user, Decl(nonInferrableTypePropagation3.ts, 8, 23))
|
||||
>age : Symbol(age, Decl(nonInferrableTypePropagation3.ts, 5, 33))
|
||||
>age : Symbol(age, Decl(nonInferrableTypePropagation3.ts, 7, 27))
|
||||
|
||||
});
|
||||
|
||||
@ -0,0 +1,44 @@
|
||||
=== tests/cases/compiler/nonInferrableTypePropagation3.ts ===
|
||||
// Repro from #53748
|
||||
|
||||
declare type Callback<Args extends any[], Out, R> = (...args: Args) => (data: Out) => R;
|
||||
>Callback : Callback<Args, Out, R>
|
||||
>args : Args
|
||||
>data : Out
|
||||
|
||||
declare function factory<Out>(): <Args extends any[], R>(callback: Callback<Args, Out, R>) => (...args: Args) => R;
|
||||
>factory : <Out>() => <Args extends any[], R>(callback: Callback<Args, Out, R>) => (...args: Args) => R
|
||||
>callback : Callback<Args, Out, R>
|
||||
>args : Args
|
||||
|
||||
const make = factory<{id: string, age: number}[]>();
|
||||
>make : <Args extends any[], R>(callback: Callback<Args, { id: string; age: number; }[], R>) => (...args: Args) => R
|
||||
>factory<{id: string, age: number}[]>() : <Args extends any[], R>(callback: Callback<Args, { id: string; age: number; }[], R>) => (...args: Args) => R
|
||||
>factory : <Out>() => <Args extends any[], R>(callback: Callback<Args, Out, R>) => (...args: Args) => R
|
||||
>id : string
|
||||
>age : number
|
||||
|
||||
const usersOverAge = make((age: number) => data => {
|
||||
>usersOverAge : (age: number) => { id: string; age: number; }[]
|
||||
>make((age: number) => data => { return data.filter(user => user.age >= age);}) : (age: number) => { id: string; age: number; }[]
|
||||
>make : <Args extends any[], R>(callback: Callback<Args, { id: string; age: number; }[], R>) => (...args: Args) => R
|
||||
>(age: number) => data => { return data.filter(user => user.age >= age);} : (age: number) => (data: { id: string; age: number; }[]) => { id: string; age: number; }[]
|
||||
>age : number
|
||||
>data => { return data.filter(user => user.age >= age);} : (data: { id: string; age: number; }[]) => { id: string; age: number; }[]
|
||||
>data : { id: string; age: number; }[]
|
||||
|
||||
return data.filter(user => user.age >= age);
|
||||
>data.filter(user => user.age >= age) : { id: string; age: number; }[]
|
||||
>data.filter : { <S extends { id: string; age: number; }>(predicate: (value: { id: string; age: number; }, index: number, array: { id: string; age: number; }[]) => value is S, thisArg?: any): S[]; (predicate: (value: { id: string; age: number; }, index: number, array: { id: string; age: number; }[]) => unknown, thisArg?: any): { id: string; age: number; }[]; }
|
||||
>data : { id: string; age: number; }[]
|
||||
>filter : { <S extends { id: string; age: number; }>(predicate: (value: { id: string; age: number; }, index: number, array: { id: string; age: number; }[]) => value is S, thisArg?: any): S[]; (predicate: (value: { id: string; age: number; }, index: number, array: { id: string; age: number; }[]) => unknown, thisArg?: any): { id: string; age: number; }[]; }
|
||||
>user => user.age >= age : (user: { id: string; age: number; }) => boolean
|
||||
>user : { id: string; age: number; }
|
||||
>user.age >= age : boolean
|
||||
>user.age : number
|
||||
>user : { id: string; age: number; }
|
||||
>age : number
|
||||
>age : number
|
||||
|
||||
});
|
||||
|
||||
13
tests/cases/compiler/nonInferrableTypePropagation3.ts
Normal file
13
tests/cases/compiler/nonInferrableTypePropagation3.ts
Normal file
@ -0,0 +1,13 @@
|
||||
// @strict: true
|
||||
// @noEmit: true
|
||||
|
||||
// Repro from #53748
|
||||
|
||||
declare type Callback<Args extends any[], Out, R> = (...args: Args) => (data: Out) => R;
|
||||
declare function factory<Out>(): <Args extends any[], R>(callback: Callback<Args, Out, R>) => (...args: Args) => R;
|
||||
|
||||
const make = factory<{id: string, age: number}[]>();
|
||||
|
||||
const usersOverAge = make((age: number) => data => {
|
||||
return data.filter(user => user.age >= age);
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user