Skip to content

Commit 0428c4a

Browse files
committed
Improve the fix to handle tuples with leading variadic elements
1 parent 399528b commit 0428c4a

4 files changed

+181
-9
lines changed

src/compiler/checker.ts

+23-9
Original file line numberDiff line numberDiff line change
@@ -23327,24 +23327,38 @@ namespace ts {
2332723327
else {
2332823328
const middleLength = targetArity - startLength - endLength;
2332923329
if (middleLength === 2) {
23330-
let impliedArity: number | undefined;
23331-
2333223330
if (elementFlags[startLength] & elementFlags[startLength + 1] & ElementFlags.Variadic && isTupleType(source)) {
2333323331
// Middle of target is [...T, ...U] and source is tuple type
23334-
impliedArity = getInferenceInfoForType(elementTypes[startLength])?.impliedArity;
23332+
const impliedArity = getInferenceInfoForType(elementTypes[startLength])?.impliedArity;
23333+
if (impliedArity !== undefined) {
23334+
// Infer slices from source based on implied arity of T.
23335+
inferFromTypes(sliceTupleType(source, startLength, endLength + sourceArity - impliedArity), elementTypes[startLength]);
23336+
inferFromTypes(sliceTupleType(source, startLength + impliedArity, endLength), elementTypes[startLength + 1]);
23337+
}
2333523338
}
23336-
else if (elementFlags[startLength] & ElementFlags.Variadic && elementFlags[startLength + 1] & ElementFlags.Rest && isTupleType(source)) {
23339+
else if (elementFlags[startLength] & ElementFlags.Variadic && elementFlags[startLength + 1] & ElementFlags.Rest) {
2333723340
// Middle of target is [...T, ...rest] and source is tuple type
23341+
// if T is constrained by a fixed-size tuple we might be able to use its arity to infer T
2333823342
const param = getInferenceInfoForType(elementTypes[startLength])?.typeParameter;
2333923343
const constraint = param && getBaseConstraintOfType(param);
2334023344
if (constraint && isTupleType(constraint) && !constraint.target.hasRestElement) {
23341-
impliedArity = constraint.target.fixedLength;
23345+
const impliedArity = constraint.target.fixedLength;
23346+
inferFromTypes(sliceTupleType(source, startLength, sourceArity - (startLength + impliedArity)), elementTypes[startLength]);
2334223347
}
2334323348
}
23344-
if (impliedArity !== undefined) {
23345-
// Infer slices from source based on implied arity of T.
23346-
inferFromTypes(sliceTupleType(source, startLength, endLength + sourceArity - impliedArity), elementTypes[startLength]);
23347-
inferFromTypes(sliceTupleType(source, startLength + impliedArity, endLength), elementTypes[startLength + 1]);
23349+
else if (elementFlags[startLength] & ElementFlags.Rest && elementFlags[startLength + 1] & ElementFlags.Variadic && isTupleType(source)) {
23350+
// Middle of target is [...rest, ...T] and source is tuple type
23351+
// if T is constrained by a fixed-size tuple we might be able to use its arity to infer T
23352+
const param = getInferenceInfoForType(elementTypes[startLength + 1])?.typeParameter;
23353+
const constraint = param && getBaseConstraintOfType(param);
23354+
if (constraint && isTupleType(constraint) && !constraint.target.hasRestElement) {
23355+
const impliedArity = constraint.target.fixedLength;
23356+
const endIndex = sourceArity - getEndElementCount(target.target, ElementFlags.Fixed);
23357+
const startIndex = endIndex - impliedArity;
23358+
const trailingSlice = createTupleType(getTypeArguments(source).slice(startIndex, endIndex), source.target.elementFlags.slice(startIndex, endIndex),
23359+
/*readonly*/ false, source.target.labeledElementDeclarations && source.target.labeledElementDeclarations.slice(startIndex, endIndex));
23360+
inferFromTypes(trailingSlice, elementTypes[startLength + 1]);
23361+
}
2334823362
}
2334923363
}
2335023364
else if (middleLength === 1 && elementFlags[startLength] & ElementFlags.Variadic) {

tests/baselines/reference/inferTypesWithFixedTupleExtendsAtVariadicPosition.symbols

+75
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,78 @@ type SubTup2VariadicTest = SubTup2Variadic<[a: 0, b: 1, ...c: number[]]>;
3939
>SubTup2VariadicTest : Symbol(SubTup2VariadicTest, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 16, 10))
4040
>SubTup2Variadic : Symbol(SubTup2Variadic, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 9, 74))
4141

42+
type SubTup2VariadicTest2 = SubTup2Variadic<[a: 0, b: 1, c: 2, ...d: number[]]>;
43+
>SubTup2VariadicTest2 : Symbol(SubTup2VariadicTest2, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 18, 73))
44+
>SubTup2Variadic : Symbol(SubTup2Variadic, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 9, 74))
45+
46+
type SubTup2TrailingVariadic<T extends unknown[]> = T extends [
47+
>SubTup2TrailingVariadic : Symbol(SubTup2TrailingVariadic, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 19, 80))
48+
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 21, 29))
49+
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 21, 29))
50+
51+
...any,
52+
...infer B extends [any, any],
53+
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 23, 10))
54+
55+
]
56+
? B
57+
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 23, 10))
58+
59+
: never;
60+
61+
type SubTup2TrailingVariadicTest = SubTup2TrailingVariadic<[...a: number[], b: 1, c: 2]>;
62+
>SubTup2TrailingVariadicTest : Symbol(SubTup2TrailingVariadicTest, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 26, 10))
63+
>SubTup2TrailingVariadic : Symbol(SubTup2TrailingVariadic, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 19, 80))
64+
65+
type SubTup2TrailingVariadicTest2 = SubTup2TrailingVariadic<[...a: number[], b: 1, c: 2, d: 3]>;
66+
>SubTup2TrailingVariadicTest2 : Symbol(SubTup2TrailingVariadicTest2, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 28, 89))
67+
>SubTup2TrailingVariadic : Symbol(SubTup2TrailingVariadic, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 19, 80))
68+
69+
type SubTup2VariadicWithLeadingFixedElements<T extends unknown[]> = T extends [
70+
>SubTup2VariadicWithLeadingFixedElements : Symbol(SubTup2VariadicWithLeadingFixedElements, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 29, 96))
71+
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 31, 45))
72+
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 31, 45))
73+
74+
any,
75+
...infer B extends [any, any],
76+
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 33, 10))
77+
78+
...any
79+
]
80+
? B
81+
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 33, 10))
82+
83+
: never;
84+
85+
type SubTup2VariadicWithLeadingFixedElementsTest = SubTup2VariadicWithLeadingFixedElements<[a: 0, b: 1, c: 2, ...d: number[]]>;
86+
>SubTup2VariadicWithLeadingFixedElementsTest : Symbol(SubTup2VariadicWithLeadingFixedElementsTest, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 37, 10))
87+
>SubTup2VariadicWithLeadingFixedElements : Symbol(SubTup2VariadicWithLeadingFixedElements, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 29, 96))
88+
89+
type SubTup2VariadicWithLeadingFixedElementsTest2 = SubTup2VariadicWithLeadingFixedElements<[a: 0, b: 1, c: 2, d: 3, ...e: number[]]>;
90+
>SubTup2VariadicWithLeadingFixedElementsTest2 : Symbol(SubTup2VariadicWithLeadingFixedElementsTest2, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 39, 127))
91+
>SubTup2VariadicWithLeadingFixedElements : Symbol(SubTup2VariadicWithLeadingFixedElements, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 29, 96))
92+
93+
type SubTup2TrailingVariadicWithTrailingFixedElements<T extends unknown[]> = T extends [
94+
>SubTup2TrailingVariadicWithTrailingFixedElements : Symbol(SubTup2TrailingVariadicWithTrailingFixedElements, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 40, 134))
95+
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 42, 54))
96+
>T : Symbol(T, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 42, 54))
97+
98+
...any,
99+
...infer B extends [any, any],
100+
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 44, 10))
101+
102+
any,
103+
]
104+
? B
105+
>B : Symbol(B, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 44, 10))
106+
107+
: never;
108+
109+
type SubTup2TrailingVariadicWithTrailingFixedElementsTest = SubTup2TrailingVariadicWithTrailingFixedElements<[...a: number[], b: 1, c: 2, d: 3]>;
110+
>SubTup2TrailingVariadicWithTrailingFixedElementsTest : Symbol(SubTup2TrailingVariadicWithTrailingFixedElementsTest, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 48, 10))
111+
>SubTup2TrailingVariadicWithTrailingFixedElements : Symbol(SubTup2TrailingVariadicWithTrailingFixedElements, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 40, 134))
112+
113+
type SubTup2TrailingVariadicWithTrailingFixedElementsTest2 = SubTup2TrailingVariadicWithTrailingFixedElements<[...a: number[], b: 1, c: 2, d: 3, e: 4]>;
114+
>SubTup2TrailingVariadicWithTrailingFixedElementsTest2 : Symbol(SubTup2TrailingVariadicWithTrailingFixedElementsTest2, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 50, 145))
115+
>SubTup2TrailingVariadicWithTrailingFixedElements : Symbol(SubTup2TrailingVariadicWithTrailingFixedElements, Decl(inferTypesWithFixedTupleExtendsAtVariadicPosition.ts, 40, 134))
116+

tests/baselines/reference/inferTypesWithFixedTupleExtendsAtVariadicPosition.types

+50
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,53 @@ type SubTup2Variadic<T extends unknown[]> = T extends [
2525
type SubTup2VariadicTest = SubTup2Variadic<[a: 0, b: 1, ...c: number[]]>;
2626
>SubTup2VariadicTest : [a: 0, b: 1]
2727

28+
type SubTup2VariadicTest2 = SubTup2Variadic<[a: 0, b: 1, c: 2, ...d: number[]]>;
29+
>SubTup2VariadicTest2 : [a: 0, b: 1]
30+
31+
type SubTup2TrailingVariadic<T extends unknown[]> = T extends [
32+
>SubTup2TrailingVariadic : SubTup2TrailingVariadic<T>
33+
34+
...any,
35+
...infer B extends [any, any],
36+
]
37+
? B
38+
: never;
39+
40+
type SubTup2TrailingVariadicTest = SubTup2TrailingVariadic<[...a: number[], b: 1, c: 2]>;
41+
>SubTup2TrailingVariadicTest : [b: 1, c: 2]
42+
43+
type SubTup2TrailingVariadicTest2 = SubTup2TrailingVariadic<[...a: number[], b: 1, c: 2, d: 3]>;
44+
>SubTup2TrailingVariadicTest2 : [c: 2, d: 3]
45+
46+
type SubTup2VariadicWithLeadingFixedElements<T extends unknown[]> = T extends [
47+
>SubTup2VariadicWithLeadingFixedElements : SubTup2VariadicWithLeadingFixedElements<T>
48+
49+
any,
50+
...infer B extends [any, any],
51+
...any
52+
]
53+
? B
54+
: never;
55+
56+
type SubTup2VariadicWithLeadingFixedElementsTest = SubTup2VariadicWithLeadingFixedElements<[a: 0, b: 1, c: 2, ...d: number[]]>;
57+
>SubTup2VariadicWithLeadingFixedElementsTest : [b: 1, c: 2]
58+
59+
type SubTup2VariadicWithLeadingFixedElementsTest2 = SubTup2VariadicWithLeadingFixedElements<[a: 0, b: 1, c: 2, d: 3, ...e: number[]]>;
60+
>SubTup2VariadicWithLeadingFixedElementsTest2 : [b: 1, c: 2]
61+
62+
type SubTup2TrailingVariadicWithTrailingFixedElements<T extends unknown[]> = T extends [
63+
>SubTup2TrailingVariadicWithTrailingFixedElements : SubTup2TrailingVariadicWithTrailingFixedElements<T>
64+
65+
...any,
66+
...infer B extends [any, any],
67+
any,
68+
]
69+
? B
70+
: never;
71+
72+
type SubTup2TrailingVariadicWithTrailingFixedElementsTest = SubTup2TrailingVariadicWithTrailingFixedElements<[...a: number[], b: 1, c: 2, d: 3]>;
73+
>SubTup2TrailingVariadicWithTrailingFixedElementsTest : [b: 1, c: 2]
74+
75+
type SubTup2TrailingVariadicWithTrailingFixedElementsTest2 = SubTup2TrailingVariadicWithTrailingFixedElements<[...a: number[], b: 1, c: 2, d: 3, e: 4]>;
76+
>SubTup2TrailingVariadicWithTrailingFixedElementsTest2 : [c: 2, d: 3]
77+

tests/cases/compiler/inferTypesWithFixedTupleExtendsAtVariadicPosition.ts

+33
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,36 @@ type SubTup2Variadic<T extends unknown[]> = T extends [
2020
: never;
2121

2222
type SubTup2VariadicTest = SubTup2Variadic<[a: 0, b: 1, ...c: number[]]>;
23+
type SubTup2VariadicTest2 = SubTup2Variadic<[a: 0, b: 1, c: 2, ...d: number[]]>;
24+
25+
type SubTup2TrailingVariadic<T extends unknown[]> = T extends [
26+
...any,
27+
...infer B extends [any, any],
28+
]
29+
? B
30+
: never;
31+
32+
type SubTup2TrailingVariadicTest = SubTup2TrailingVariadic<[...a: number[], b: 1, c: 2]>;
33+
type SubTup2TrailingVariadicTest2 = SubTup2TrailingVariadic<[...a: number[], b: 1, c: 2, d: 3]>;
34+
35+
type SubTup2VariadicWithLeadingFixedElements<T extends unknown[]> = T extends [
36+
any,
37+
...infer B extends [any, any],
38+
...any
39+
]
40+
? B
41+
: never;
42+
43+
type SubTup2VariadicWithLeadingFixedElementsTest = SubTup2VariadicWithLeadingFixedElements<[a: 0, b: 1, c: 2, ...d: number[]]>;
44+
type SubTup2VariadicWithLeadingFixedElementsTest2 = SubTup2VariadicWithLeadingFixedElements<[a: 0, b: 1, c: 2, d: 3, ...e: number[]]>;
45+
46+
type SubTup2TrailingVariadicWithTrailingFixedElements<T extends unknown[]> = T extends [
47+
...any,
48+
...infer B extends [any, any],
49+
any,
50+
]
51+
? B
52+
: never;
53+
54+
type SubTup2TrailingVariadicWithTrailingFixedElementsTest = SubTup2TrailingVariadicWithTrailingFixedElements<[...a: number[], b: 1, c: 2, d: 3]>;
55+
type SubTup2TrailingVariadicWithTrailingFixedElementsTest2 = SubTup2TrailingVariadicWithTrailingFixedElements<[...a: number[], b: 1, c: 2, d: 3, e: 4]>;

0 commit comments

Comments
 (0)