Skip to content

Commit 8d58c8d

Browse files
authored
Base signatures resolve only the type parameters local to the signature, not all type parameters (#42703)
1 parent 6da2625 commit 8d58c8d

6 files changed

+49
-2
lines changed

src/compiler/checker.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12244,9 +12244,20 @@ namespace ts {
1224412244
function getBaseSignature(signature: Signature) {
1224512245
const typeParameters = signature.typeParameters;
1224612246
if (typeParameters) {
12247+
if (signature.baseSignatureCache) {
12248+
return signature.baseSignatureCache;
12249+
}
1224712250
const typeEraser = createTypeEraser(typeParameters);
12248-
const baseConstraints = map(typeParameters, tp => instantiateType(getBaseConstraintOfType(tp), typeEraser) || unknownType);
12249-
return instantiateSignature(signature, createTypeMapper(typeParameters, baseConstraints), /*eraseTypeParameters*/ true);
12251+
const baseConstraintMapper = createTypeMapper(typeParameters, map(typeParameters, tp => getConstraintOfTypeParameter(tp) || unknownType));
12252+
let baseConstraints: readonly Type[] = map(typeParameters, tp => instantiateType(tp, baseConstraintMapper) || unknownType);
12253+
// Run N type params thru the immediate constraint mapper up to N times
12254+
// This way any noncircular interdependent type parameters are definitely resolved to their external dependencies
12255+
for (let i = 0; i < typeParameters.length - 1; i++) {
12256+
baseConstraints = instantiateTypes(baseConstraints, baseConstraintMapper);
12257+
}
12258+
// and then apply a type eraser to remove any remaining circularly dependent type parameters
12259+
baseConstraints = instantiateTypes(baseConstraints, typeEraser);
12260+
return signature.baseSignatureCache = instantiateSignature(signature, createTypeMapper(typeParameters, baseConstraints), /*eraseTypeParameters*/ true);
1225012261
}
1225112262
return signature;
1225212263
}

src/compiler/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5550,6 +5550,8 @@ namespace ts {
55505550
/* @internal */
55515551
canonicalSignatureCache?: Signature; // Canonical version of signature (deferred)
55525552
/* @internal */
5553+
baseSignatureCache?: Signature; // Base version of signature (deferred)
5554+
/* @internal */
55535555
optionalCallSignatureCache?: { inner?: Signature, outer?: Signature }; // Optional chained call version of signature (deferred)
55545556
/* @internal */
55555557
isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//// [conditionalTypeGenericInSignatureTypeParameterConstraint.ts]
2+
// should be x
3+
type H_inline1<x> = (<o extends x>() => o) extends (() => infer o) ? o : never;
4+
5+
type Result = H_inline1<string>; // should be `string`
6+
7+
//// [conditionalTypeGenericInSignatureTypeParameterConstraint.js]
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
=== tests/cases/compiler/conditionalTypeGenericInSignatureTypeParameterConstraint.ts ===
2+
// should be x
3+
type H_inline1<x> = (<o extends x>() => o) extends (() => infer o) ? o : never;
4+
>H_inline1 : Symbol(H_inline1, Decl(conditionalTypeGenericInSignatureTypeParameterConstraint.ts, 0, 0))
5+
>x : Symbol(x, Decl(conditionalTypeGenericInSignatureTypeParameterConstraint.ts, 1, 15))
6+
>o : Symbol(o, Decl(conditionalTypeGenericInSignatureTypeParameterConstraint.ts, 1, 22))
7+
>x : Symbol(x, Decl(conditionalTypeGenericInSignatureTypeParameterConstraint.ts, 1, 15))
8+
>o : Symbol(o, Decl(conditionalTypeGenericInSignatureTypeParameterConstraint.ts, 1, 22))
9+
>o : Symbol(o, Decl(conditionalTypeGenericInSignatureTypeParameterConstraint.ts, 1, 63))
10+
>o : Symbol(o, Decl(conditionalTypeGenericInSignatureTypeParameterConstraint.ts, 1, 63))
11+
12+
type Result = H_inline1<string>; // should be `string`
13+
>Result : Symbol(Result, Decl(conditionalTypeGenericInSignatureTypeParameterConstraint.ts, 1, 79))
14+
>H_inline1 : Symbol(H_inline1, Decl(conditionalTypeGenericInSignatureTypeParameterConstraint.ts, 0, 0))
15+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
=== tests/cases/compiler/conditionalTypeGenericInSignatureTypeParameterConstraint.ts ===
2+
// should be x
3+
type H_inline1<x> = (<o extends x>() => o) extends (() => infer o) ? o : never;
4+
>H_inline1 : x
5+
6+
type Result = H_inline1<string>; // should be `string`
7+
>Result : string
8+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// should be x
2+
type H_inline1<x> = (<o extends x>() => o) extends (() => infer o) ? o : never;
3+
4+
type Result = H_inline1<string>; // should be `string`

0 commit comments

Comments
 (0)