Skip to content

Commit 399528b

Browse files
committed
Infer fixed-size tuples from infer type parameters with extends clauses at variadic positions
1 parent e14a229 commit 399528b

4 files changed

+108
-6
lines changed

src/compiler/checker.ts

+18-6
Original file line numberDiff line numberDiff line change
@@ -23326,13 +23326,25 @@ namespace ts {
2332623326
}
2332723327
else {
2332823328
const middleLength = targetArity - startLength - endLength;
23329-
if (middleLength === 2 && elementFlags[startLength] & elementFlags[startLength + 1] & ElementFlags.Variadic && isTupleType(source)) {
23330-
// Middle of target is [...T, ...U] and source is tuple type
23331-
const targetInfo = getInferenceInfoForType(elementTypes[startLength]);
23332-
if (targetInfo && targetInfo.impliedArity !== undefined) {
23329+
if (middleLength === 2) {
23330+
let impliedArity: number | undefined;
23331+
23332+
if (elementFlags[startLength] & elementFlags[startLength + 1] & ElementFlags.Variadic && isTupleType(source)) {
23333+
// Middle of target is [...T, ...U] and source is tuple type
23334+
impliedArity = getInferenceInfoForType(elementTypes[startLength])?.impliedArity;
23335+
}
23336+
else if (elementFlags[startLength] & ElementFlags.Variadic && elementFlags[startLength + 1] & ElementFlags.Rest && isTupleType(source)) {
23337+
// Middle of target is [...T, ...rest] and source is tuple type
23338+
const param = getInferenceInfoForType(elementTypes[startLength])?.typeParameter;
23339+
const constraint = param && getBaseConstraintOfType(param);
23340+
if (constraint && isTupleType(constraint) && !constraint.target.hasRestElement) {
23341+
impliedArity = constraint.target.fixedLength;
23342+
}
23343+
}
23344+
if (impliedArity !== undefined) {
2333323345
// Infer slices from source based on implied arity of T.
23334-
inferFromTypes(sliceTupleType(source, startLength, endLength + sourceArity - targetInfo.impliedArity), elementTypes[startLength]);
23335-
inferFromTypes(sliceTupleType(source, startLength + targetInfo.impliedArity, endLength), elementTypes[startLength + 1]);
23346+
inferFromTypes(sliceTupleType(source, startLength, endLength + sourceArity - impliedArity), elementTypes[startLength]);
23347+
inferFromTypes(sliceTupleType(source, startLength + impliedArity, endLength), elementTypes[startLength + 1]);
2333623348
}
2333723349
}
2333823350
else if (middleLength === 1 && elementFlags[startLength] & ElementFlags.Variadic) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
=== tests/cases/compiler/inferTypesWithFixedTupleExtendsAtVariadicPosition.ts ===
2+
// repro #51138
3+
4+
type SubTup2FixedLength<T extends unknown[]> = T extends [
5+
>SubTup2FixedLength : Symbol(SubTup2FixedLength, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 0, 0))
6+
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 2, 24))
7+
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 2, 24))
8+
9+
...infer B extends [any, any],
10+
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 3, 10))
11+
12+
any
13+
]
14+
? B
15+
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 3, 10))
16+
17+
: never;
18+
19+
type SubTup2FixedLengthTest = SubTup2FixedLength<[a: 0, b: 1, c: number]>;
20+
>SubTup2FixedLengthTest : Symbol(SubTup2FixedLengthTest, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 7, 10))
21+
>SubTup2FixedLength : Symbol(SubTup2FixedLength, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 0, 0))
22+
23+
type SubTup2Variadic<T extends unknown[]> = T extends [
24+
>SubTup2Variadic : Symbol(SubTup2Variadic, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 9, 74))
25+
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 11, 21))
26+
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 11, 21))
27+
28+
...infer B extends [any, any],
29+
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 12, 10))
30+
31+
...any
32+
]
33+
? B
34+
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 12, 10))
35+
36+
: never;
37+
38+
type SubTup2VariadicTest = SubTup2Variadic<[a: 0, b: 1, ...c: number[]]>;
39+
>SubTup2VariadicTest : Symbol(SubTup2VariadicTest, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 16, 10))
40+
>SubTup2Variadic : Symbol(SubTup2Variadic, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 9, 74))
41+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
=== tests/cases/compiler/inferTypesWithFixedTupleExtendsAtVariadicPosition.ts ===
2+
// repro #51138
3+
4+
type SubTup2FixedLength<T extends unknown[]> = T extends [
5+
>SubTup2FixedLength : SubTup2FixedLength<T>
6+
7+
...infer B extends [any, any],
8+
any
9+
]
10+
? B
11+
: never;
12+
13+
type SubTup2FixedLengthTest = SubTup2FixedLength<[a: 0, b: 1, c: number]>;
14+
>SubTup2FixedLengthTest : [a: 0, b: 1]
15+
16+
type SubTup2Variadic<T extends unknown[]> = T extends [
17+
>SubTup2Variadic : SubTup2Variadic<T>
18+
19+
...infer B extends [any, any],
20+
...any
21+
]
22+
? B
23+
: never;
24+
25+
type SubTup2VariadicTest = SubTup2Variadic<[a: 0, b: 1, ...c: number[]]>;
26+
>SubTup2VariadicTest : [a: 0, b: 1]
27+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// @strict: true
2+
// @noEmit: true
3+
4+
// repro #51138
5+
6+
type SubTup2FixedLength<T extends unknown[]> = T extends [
7+
...infer B extends [any, any],
8+
any
9+
]
10+
? B
11+
: never;
12+
13+
type SubTup2FixedLengthTest = SubTup2FixedLength<[a: 0, b: 1, c: number]>;
14+
15+
type SubTup2Variadic<T extends unknown[]> = T extends [
16+
...infer B extends [any, any],
17+
...any
18+
]
19+
? B
20+
: never;
21+
22+
type SubTup2VariadicTest = SubTup2Variadic<[a: 0, b: 1, ...c: number[]]>;

0 commit comments

Comments
 (0)