Skip to content

Commit d479206

Browse files
authored
Variadic tuple types (microsoft#39094)
* Initial implementation of variadic tuple types * Accept new baselines * Handle variadic elements in tuple type inference * Special case inference between tuples with matching structure * Restore check that rest element is last element * Handle variadic tuples in relationship checking * Accept new baselines * Infer readonly constraints when inferring from readonly tuples * Fix lint issues * T assignable to readonly [...T] and [...T] assignable to T * Consistent tuple normalization * Create variadic tuple types from array literal expressions * Accept new baselines * Array literals have tuple types when contextual type is readonly * Accept new baselines * Optional elements before required elements become required elements * Update logic for rest parameters and spread arguments * Revert special case of contextual readonly array type * Accept new baselines * Fix lint issue * Switch entirely to createTupleType based on element flags * Don't infer readonly tuple types when inferring to variadic elements * Handle mapped types applied to generic tuple types * Handle constraint of indexed access type with generic tuple type * Accept new baselines * Address CR feedback * Simplify indexed access types involving generic tuple types * Propagate checkMode into getSpreadArgumentType * Guard against missing globalArrayType * Inference to [...T, ...U] based on implied arity of T * Accept new baselines * Add tests * Emit .d.ts from tests * Address CR feedback
1 parent e6aedfd commit d479206

File tree

83 files changed

+4280
-700
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+4280
-700
lines changed

src/compiler/checker.ts

Lines changed: 599 additions & 309 deletions
Large diffs are not rendered by default.

src/compiler/core.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,6 +1201,14 @@ namespace ts {
12011201
return values;
12021202
}
12031203

1204+
export function arrayOf<T>(count: number, f: (index: number) => T): T[] {
1205+
const result = new Array(count);
1206+
for (let i = 0; i < count; i++) {
1207+
result[i] = f(i);
1208+
}
1209+
return result;
1210+
}
1211+
12041212
/** Shims `Array.from`. */
12051213
export function arrayFrom<T, U>(iterator: Iterator<T> | IterableIterator<T>, map: (t: T) => U): U[];
12061214
export function arrayFrom<T>(iterator: Iterator<T> | IterableIterator<T>): T[];

src/compiler/diagnosticMessages.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2414,6 +2414,26 @@
24142414
"category": "Error",
24152415
"code": 2617
24162416
},
2417+
"Source has {0} element(s) but target requires {1}.": {
2418+
"category": "Error",
2419+
"code": 2618
2420+
},
2421+
"Source has {0} element(s) but target allows only {1}.": {
2422+
"category": "Error",
2423+
"code": 2619
2424+
},
2425+
"Target requires {0} element(s) but source may have fewer.": {
2426+
"category": "Error",
2427+
"code": 2620
2428+
},
2429+
"Target allows only {0} element(s) but source may have more.": {
2430+
"category": "Error",
2431+
"code": 2621
2432+
},
2433+
"Element at index {0} is variadic in one type but not in the other.": {
2434+
"category": "Error",
2435+
"code": 2622
2436+
},
24172437

24182438
"Cannot augment module '{0}' with value exports because it resolves to a non-module entity.": {
24192439
"category": "Error",

src/compiler/types.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5100,9 +5100,20 @@ namespace ts {
51005100
variances?: VarianceFlags[]; // Variance of each type parameter
51015101
}
51025102

5103+
export const enum ElementFlags {
5104+
Required = 1 << 0, // T
5105+
Optional = 1 << 1, // T?
5106+
Rest = 1 << 2, // ...T[]
5107+
Variadic = 1 << 3, // ...T
5108+
Variable = Rest | Variadic,
5109+
}
5110+
51035111
export interface TupleType extends GenericType {
5112+
elementFlags: readonly ElementFlags[];
51045113
minLength: number;
5114+
fixedLength: number;
51055115
hasRestElement: boolean;
5116+
combinedFlags: ElementFlags;
51065117
readonly: boolean;
51075118
labeledElementDeclarations?: readonly (NamedTupleMember | ParameterDeclaration)[];
51085119
}
@@ -5422,6 +5433,7 @@ namespace ts {
54225433
priority?: InferencePriority; // Priority of current inference set
54235434
topLevel: boolean; // True if all inferences are to top level occurrences
54245435
isFixed: boolean; // True if inferences are fixed
5436+
impliedArity?: number;
54255437
}
54265438

54275439
/* @internal */

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2538,9 +2538,19 @@ declare namespace ts {
25382538
}
25392539
export interface GenericType extends InterfaceType, TypeReference {
25402540
}
2541+
export enum ElementFlags {
2542+
Required = 1,
2543+
Optional = 2,
2544+
Rest = 4,
2545+
Variadic = 8,
2546+
Variable = 12
2547+
}
25412548
export interface TupleType extends GenericType {
2549+
elementFlags: readonly ElementFlags[];
25422550
minLength: number;
2551+
fixedLength: number;
25432552
hasRestElement: boolean;
2553+
combinedFlags: ElementFlags;
25442554
readonly: boolean;
25452555
labeledElementDeclarations?: readonly (NamedTupleMember | ParameterDeclaration)[];
25462556
}

tests/baselines/reference/api/typescript.d.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2538,9 +2538,19 @@ declare namespace ts {
25382538
}
25392539
export interface GenericType extends InterfaceType, TypeReference {
25402540
}
2541+
export enum ElementFlags {
2542+
Required = 1,
2543+
Optional = 2,
2544+
Rest = 4,
2545+
Variadic = 8,
2546+
Variable = 12
2547+
}
25412548
export interface TupleType extends GenericType {
2549+
elementFlags: readonly ElementFlags[];
25422550
minLength: number;
2551+
fixedLength: number;
25432552
hasRestElement: boolean;
2553+
combinedFlags: ElementFlags;
25442554
readonly: boolean;
25452555
labeledElementDeclarations?: readonly (NamedTupleMember | ParameterDeclaration)[];
25462556
}

tests/baselines/reference/argumentExpressionContextualTyping.errors.txt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
tests/cases/conformance/expressions/contextualTyping/argumentExpressionContextualTyping.ts(16,5): error TS2345: Argument of type '(string | number | boolean)[]' is not assignable to parameter of type '[string, number, boolean]'.
2-
Type '(string | number | boolean)[]' is missing the following properties from type '[string, number, boolean]': 0, 1, 2
2+
Target requires 3 element(s) but source may have fewer.
33
tests/cases/conformance/expressions/contextualTyping/argumentExpressionContextualTyping.ts(17,5): error TS2345: Argument of type '[string, number, true, ...(string | number | boolean)[]]' is not assignable to parameter of type '[string, number, boolean]'.
4-
Types of property 'length' are incompatible.
5-
Type 'number' is not assignable to type '3'.
4+
Target allows only 3 element(s) but source may have more.
65
tests/cases/conformance/expressions/contextualTyping/argumentExpressionContextualTyping.ts(18,5): error TS2345: Argument of type '{ x: (string | number)[]; y: { c: boolean; d: string; e: number; }; }' is not assignable to parameter of type '{ x: [any, any]; y: { c: any; d: any; e: any; }; }'.
76
Types of property 'x' are incompatible.
8-
Type '(string | number)[]' is missing the following properties from type '[any, any]': 0, 1
7+
Type '(string | number)[]' is not assignable to type '[any, any]'.
8+
Target requires 2 element(s) but source may have fewer.
99

1010

1111
==== tests/cases/conformance/expressions/contextualTyping/argumentExpressionContextualTyping.ts (3 errors) ====
@@ -27,14 +27,14 @@ tests/cases/conformance/expressions/contextualTyping/argumentExpressionContextua
2727
baz(array); // Error
2828
~~~~~
2929
!!! error TS2345: Argument of type '(string | number | boolean)[]' is not assignable to parameter of type '[string, number, boolean]'.
30-
!!! error TS2345: Type '(string | number | boolean)[]' is missing the following properties from type '[string, number, boolean]': 0, 1, 2
30+
!!! error TS2345: Target requires 3 element(s) but source may have fewer.
3131
baz(["string", 1, true, ...array]); // Error
3232
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3333
!!! error TS2345: Argument of type '[string, number, true, ...(string | number | boolean)[]]' is not assignable to parameter of type '[string, number, boolean]'.
34-
!!! error TS2345: Types of property 'length' are incompatible.
35-
!!! error TS2345: Type 'number' is not assignable to type '3'.
34+
!!! error TS2345: Target allows only 3 element(s) but source may have more.
3635
foo(o); // Error because x has an array type namely (string|number)[]
3736
~
3837
!!! error TS2345: Argument of type '{ x: (string | number)[]; y: { c: boolean; d: string; e: number; }; }' is not assignable to parameter of type '{ x: [any, any]; y: { c: any; d: any; e: any; }; }'.
3938
!!! error TS2345: Types of property 'x' are incompatible.
40-
!!! error TS2345: Type '(string | number)[]' is missing the following properties from type '[any, any]': 0, 1
39+
!!! error TS2345: Type '(string | number)[]' is not assignable to type '[any, any]'.
40+
!!! error TS2345: Target requires 2 element(s) but source may have fewer.

tests/baselines/reference/arityAndOrderCompatibility01.errors.txt

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(15,12): error TS2493: Tuple type '[string, number]' of length '2' has no element at index '2'.
22
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(17,5): error TS2461: Type '{ 0: string; 1: number; length: 2; }' is not an array type.
3-
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(18,5): error TS2741: Property '2' is missing in type '[string, number]' but required in type '[number, number, number]'.
3+
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(18,5): error TS2322: Type '[string, number]' is not assignable to type '[number, number, number]'.
4+
Source has 2 element(s) but target requires 3.
45
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(19,5): error TS2741: Property '2' is missing in type 'StrNum' but required in type '[number, number, number]'.
56
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(20,5): error TS2322: Type '{ 0: string; 1: number; length: 2; }' is not assignable to type '[number, number, number]'.
6-
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(21,5): error TS2741: Property '2' is missing in type '[string, number]' but required in type '[string, number, number]'.
7+
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(21,5): error TS2322: Type '[string, number]' is not assignable to type '[string, number, number]'.
8+
Source has 2 element(s) but target requires 3.
79
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(22,5): error TS2741: Property '2' is missing in type 'StrNum' but required in type '[string, number, number]'.
810
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(23,5): error TS2322: Type '{ 0: string; 1: number; length: 2; }' is not assignable to type '[string, number, number]'.
911
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(24,5): error TS2322: Type '[string, number]' is not assignable to type '[number]'.
10-
Types of property '0' are incompatible.
11-
Type 'string' is not assignable to type 'number'.
12+
Source has 2 element(s) but target allows only 1.
1213
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(25,5): error TS2322: Type 'StrNum' is not assignable to type '[number]'.
1314
Types of property '0' are incompatible.
1415
Type 'string' is not assignable to type 'number'.
1516
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(26,5): error TS2322: Type '{ 0: string; 1: number; length: 2; }' is not assignable to type '[number]'.
1617
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(27,5): error TS2322: Type '[string, number]' is not assignable to type '[string]'.
17-
Types of property 'length' are incompatible.
18-
Type '2' is not assignable to type '1'.
18+
Source has 2 element(s) but target allows only 1.
1919
tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(28,5): error TS2322: Type 'StrNum' is not assignable to type '[string]'.
2020
Types of property 'length' are incompatible.
2121
Type '2' is not assignable to type '1'.
@@ -52,7 +52,8 @@ tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(32,5): error
5252
!!! error TS2461: Type '{ 0: string; 1: number; length: 2; }' is not an array type.
5353
var j1: [number, number, number] = x;
5454
~~
55-
!!! error TS2741: Property '2' is missing in type '[string, number]' but required in type '[number, number, number]'.
55+
!!! error TS2322: Type '[string, number]' is not assignable to type '[number, number, number]'.
56+
!!! error TS2322: Source has 2 element(s) but target requires 3.
5657
var j2: [number, number, number] = y;
5758
~~
5859
!!! error TS2741: Property '2' is missing in type 'StrNum' but required in type '[number, number, number]'.
@@ -61,7 +62,8 @@ tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(32,5): error
6162
!!! error TS2322: Type '{ 0: string; 1: number; length: 2; }' is not assignable to type '[number, number, number]'.
6263
var k1: [string, number, number] = x;
6364
~~
64-
!!! error TS2741: Property '2' is missing in type '[string, number]' but required in type '[string, number, number]'.
65+
!!! error TS2322: Type '[string, number]' is not assignable to type '[string, number, number]'.
66+
!!! error TS2322: Source has 2 element(s) but target requires 3.
6567
var k2: [string, number, number] = y;
6668
~~
6769
!!! error TS2741: Property '2' is missing in type 'StrNum' but required in type '[string, number, number]'.
@@ -71,8 +73,7 @@ tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(32,5): error
7173
var l1: [number] = x;
7274
~~
7375
!!! error TS2322: Type '[string, number]' is not assignable to type '[number]'.
74-
!!! error TS2322: Types of property '0' are incompatible.
75-
!!! error TS2322: Type 'string' is not assignable to type 'number'.
76+
!!! error TS2322: Source has 2 element(s) but target allows only 1.
7677
var l2: [number] = y;
7778
~~
7879
!!! error TS2322: Type 'StrNum' is not assignable to type '[number]'.
@@ -84,8 +85,7 @@ tests/cases/conformance/types/tuple/arityAndOrderCompatibility01.ts(32,5): error
8485
var m1: [string] = x;
8586
~~
8687
!!! error TS2322: Type '[string, number]' is not assignable to type '[string]'.
87-
!!! error TS2322: Types of property 'length' are incompatible.
88-
!!! error TS2322: Type '2' is not assignable to type '1'.
88+
!!! error TS2322: Source has 2 element(s) but target allows only 1.
8989
var m2: [string] = y;
9090
~~
9191
!!! error TS2322: Type 'StrNum' is not assignable to type '[string]'.
Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
11
tests/cases/conformance/expressions/contextualTyping/arrayLiteralExpressionContextualTyping.ts(6,5): error TS2322: Type '[number, number, number, number]' is not assignable to type '[number, number, number]'.
2-
Types of property 'length' are incompatible.
3-
Type '4' is not assignable to type '3'.
2+
Source has 4 element(s) but target allows only 3.
43
tests/cases/conformance/expressions/contextualTyping/arrayLiteralExpressionContextualTyping.ts(7,5): error TS2322: Type '[number, number, number, string]' is not assignable to type '[string | number, string | number, string | number]'.
5-
Types of property 'length' are incompatible.
6-
Type '4' is not assignable to type '3'.
4+
Source has 4 element(s) but target allows only 3.
75
tests/cases/conformance/expressions/contextualTyping/arrayLiteralExpressionContextualTyping.ts(8,5): error TS2322: Type '[number, number, number, string]' is not assignable to type '[number, number, number]'.
8-
Types of property 'length' are incompatible.
9-
Type '4' is not assignable to type '3'.
6+
Source has 4 element(s) but target allows only 3.
107
tests/cases/conformance/expressions/contextualTyping/arrayLiteralExpressionContextualTyping.ts(14,5): error TS2322: Type '[number, number, number, number, number, number]' is not assignable to type '[number, number, number]'.
11-
Types of property 'length' are incompatible.
12-
Type '6' is not assignable to type '3'.
8+
Source has 6 element(s) but target allows only 3.
139

1410

1511
==== tests/cases/conformance/expressions/contextualTyping/arrayLiteralExpressionContextualTyping.ts (4 errors) ====
@@ -21,18 +17,15 @@ tests/cases/conformance/expressions/contextualTyping/arrayLiteralExpressionConte
2117
var tup: [number, number, number] = [1, 2, 3, 4];
2218
~~~
2319
!!! error TS2322: Type '[number, number, number, number]' is not assignable to type '[number, number, number]'.
24-
!!! error TS2322: Types of property 'length' are incompatible.
25-
!!! error TS2322: Type '4' is not assignable to type '3'.
20+
!!! error TS2322: Source has 4 element(s) but target allows only 3.
2621
var tup1: [number|string, number|string, number|string] = [1, 2, 3, "string"];
2722
~~~~
2823
!!! error TS2322: Type '[number, number, number, string]' is not assignable to type '[string | number, string | number, string | number]'.
29-
!!! error TS2322: Types of property 'length' are incompatible.
30-
!!! error TS2322: Type '4' is not assignable to type '3'.
24+
!!! error TS2322: Source has 4 element(s) but target allows only 3.
3125
var tup2: [number, number, number] = [1, 2, 3, "string"]; // Error
3226
~~~~
3327
!!! error TS2322: Type '[number, number, number, string]' is not assignable to type '[number, number, number]'.
34-
!!! error TS2322: Types of property 'length' are incompatible.
35-
!!! error TS2322: Type '4' is not assignable to type '3'.
28+
!!! error TS2322: Source has 4 element(s) but target allows only 3.
3629

3730
// In a contextually typed array literal expression containing one or more spread elements,
3831
// an element expression at index N is contextually typed by the numeric index type of the contextual type, if any.
@@ -41,6 +34,5 @@ tests/cases/conformance/expressions/contextualTyping/arrayLiteralExpressionConte
4134
var spr2:[number, number, number] = [1, 2, 3, ...tup]; // Error
4235
~~~~
4336
!!! error TS2322: Type '[number, number, number, number, number, number]' is not assignable to type '[number, number, number]'.
44-
!!! error TS2322: Types of property 'length' are incompatible.
45-
!!! error TS2322: Type '6' is not assignable to type '3'.
37+
!!! error TS2322: Source has 6 element(s) but target allows only 3.
4638

tests/baselines/reference/arrayLiterals3.errors.txt

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(10,5): error TS2739: Type '[]' is missing the following properties from type '[any, any, any]': 0, 1, 2
1+
tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(10,5): error TS2322: Type '[]' is not assignable to type '[any, any, any]'.
2+
Source has 0 element(s) but target requires 3.
23
tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(11,38): error TS2322: Type 'string' is not assignable to type 'boolean'.
34
tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(11,48): error TS2322: Type 'number' is not assignable to type 'string'.
45
tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(11,51): error TS2322: Type 'boolean' is not assignable to type 'number'.
56
tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(17,5): error TS2322: Type '[number, number, string, boolean]' is not assignable to type '[number, number]'.
6-
Types of property 'length' are incompatible.
7-
Type '4' is not assignable to type '2'.
8-
tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(33,5): error TS2739: Type 'number[]' is missing the following properties from type '[number, number, number]': 0, 1, 2
7+
Source has 4 element(s) but target allows only 2.
8+
tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(33,5): error TS2322: Type 'number[]' is not assignable to type '[number, number, number]'.
9+
Target requires 3 element(s) but source may have fewer.
910
tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(34,5): error TS2322: Type '(string | number)[]' is not assignable to type 'myArray'.
1011
The types returned by 'pop()' are incompatible between these types.
1112
Type 'string | number' is not assignable to type 'Number'.
@@ -24,7 +25,8 @@ tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(34,5): error
2425

2526
var a0: [any, any, any] = []; // Error
2627
~~
27-
!!! error TS2739: Type '[]' is missing the following properties from type '[any, any, any]': 0, 1, 2
28+
!!! error TS2322: Type '[]' is not assignable to type '[any, any, any]'.
29+
!!! error TS2322: Source has 0 element(s) but target requires 3.
2830
var a1: [boolean, string, number] = ["string", 1, true]; // Error
2931
~~~~~~~~
3032
!!! error TS2322: Type 'string' is not assignable to type 'boolean'.
@@ -40,8 +42,7 @@ tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(34,5): error
4042
var [b1, b2]: [number, number] = [1, 2, "string", true];
4143
~~~~~~~~
4244
!!! error TS2322: Type '[number, number, string, boolean]' is not assignable to type '[number, number]'.
43-
!!! error TS2322: Types of property 'length' are incompatible.
44-
!!! error TS2322: Type '4' is not assignable to type '2'.
45+
!!! error TS2322: Source has 4 element(s) but target allows only 2.
4546

4647
// The resulting type an array literal expression is determined as follows:
4748
// - the resulting type is an array type with an element type that is the union of the types of the
@@ -59,7 +60,8 @@ tests/cases/conformance/expressions/arrayLiterals/arrayLiterals3.ts(34,5): error
5960
var c0: tup = [...temp2]; // Error
6061
var c1: [number, number, number] = [...temp1]; // Error cannot assign number[] to [number, number, number]
6162
~~
62-
!!! error TS2739: Type 'number[]' is missing the following properties from type '[number, number, number]': 0, 1, 2
63+
!!! error TS2322: Type 'number[]' is not assignable to type '[number, number, number]'.
64+
!!! error TS2322: Target requires 3 element(s) but source may have fewer.
6365
var c2: myArray = [...temp1, ...temp]; // Error cannot assign (number|string)[] to number[]
6466
~~
6567
!!! error TS2322: Type '(string | number)[]' is not assignable to type 'myArray'.

0 commit comments

Comments
 (0)