Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Leading and middle rest elements in tuple types #41544

Merged
merged 7 commits into from
Jan 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
250 changes: 139 additions & 111 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

32 changes: 26 additions & 6 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -843,10 +843,6 @@
"category": "Error",
"code": 1255
},
"A rest element must be last in a tuple type.": {
"category": "Error",
"code": 1256
},
"A required element cannot follow an optional element.": {
"category": "Error",
"code": 1257
Expand Down Expand Up @@ -875,6 +871,14 @@
"category": "Error",
"code": 1264
},
"A rest element cannot follow another rest element.": {
"category": "Error",
"code": 1265
},
"An optional element cannot follow a rest element.": {
"category": "Error",
"code": 1266
},

"'with' statements are not allowed in an async function block.": {
"category": "Error",
Expand Down Expand Up @@ -2469,9 +2473,25 @@
"category": "Error",
"code": 2621
},
"Element at index {0} is variadic in one type but not in the other.": {
"Source provides no match for required element at position {0} in target.": {
"category": "Error",
"code": 2623
},
"Source provides no match for variadic element at position {0} in target.": {
"category": "Error",
"code": 2624
},
"Variadic element at position {0} in source does not match element at position {1} in target.": {
"category": "Error",
"code": 2625
},
"Type at position {0} in source is not compatible with type at position {1} in target.": {
"category": "Error",
"code": 2626
},
"Type at positions {0} through {1} in source is not compatible with type at position {2} in target.": {
"category": "Error",
"code": 2622
"code": 2627
},

"Cannot augment module '{0}' with value exports because it resolves to a non-module entity.": {
Expand Down
19 changes: 11 additions & 8 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5166,18 +5166,21 @@ namespace ts {
}

export const enum ElementFlags {
Required = 1 << 0, // T
Optional = 1 << 1, // T?
Rest = 1 << 2, // ...T[]
Variadic = 1 << 3, // ...T
Variable = Rest | Variadic,
Required = 1 << 0, // T
Optional = 1 << 1, // T?
Rest = 1 << 2, // ...T[]
Variadic = 1 << 3, // ...T
Fixed = Required | Optional,
Variable = Rest | Variadic,
NonRequired = Optional | Rest | Variadic,
NonRest = Required | Optional | Variadic,
}

export interface TupleType extends GenericType {
elementFlags: readonly ElementFlags[];
minLength: number;
fixedLength: number;
hasRestElement: boolean;
minLength: number; // Number of required or variadic elements
fixedLength: number; // Number of initial required or optional elements
hasRestElement: boolean; // True if tuple has any rest or variadic elements
combinedFlags: ElementFlags;
readonly: boolean;
labeledElementDeclarations?: readonly (NamedTupleMember | ParameterDeclaration)[];
Expand Down
5 changes: 4 additions & 1 deletion tests/baselines/reference/api/tsserverlibrary.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2590,7 +2590,10 @@ declare namespace ts {
Optional = 2,
Rest = 4,
Variadic = 8,
Variable = 12
Fixed = 3,
Variable = 12,
NonRequired = 14,
NonRest = 11
}
export interface TupleType extends GenericType {
elementFlags: readonly ElementFlags[];
Expand Down
5 changes: 4 additions & 1 deletion tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2590,7 +2590,10 @@ declare namespace ts {
Optional = 2,
Rest = 4,
Variadic = 8,
Variable = 12
Fixed = 3,
Variable = 12,
NonRequired = 14,
NonRest = 11
}
export interface TupleType extends GenericType {
elementFlags: readonly ElementFlags[];
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/for-of39.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ tests/cases/conformance/es6/for-ofStatements/for-of39.ts(1,11): error TS2769: No
Type 'IteratorYieldResult<[string, number] | [string, true]>' is not assignable to type 'IteratorYieldResult<readonly [string, boolean]>'.
Type '[string, number] | [string, true]' is not assignable to type 'readonly [string, boolean]'.
Type '[string, number]' is not assignable to type 'readonly [string, boolean]'.
Types of property '1' are incompatible.
Type at position 1 in source is not compatible with type at position 1 in target.
Type 'number' is not assignable to type 'boolean'.
Overload 2 of 3, '(entries?: readonly (readonly [string, boolean])[]): Map<string, boolean>', gave the following error.
Type 'number' is not assignable to type 'boolean'.
Expand All @@ -25,7 +25,7 @@ tests/cases/conformance/es6/for-ofStatements/for-of39.ts(1,11): error TS2769: No
!!! error TS2769: Type 'IteratorYieldResult<[string, number] | [string, true]>' is not assignable to type 'IteratorYieldResult<readonly [string, boolean]>'.
!!! error TS2769: Type '[string, number] | [string, true]' is not assignable to type 'readonly [string, boolean]'.
!!! error TS2769: Type '[string, number]' is not assignable to type 'readonly [string, boolean]'.
!!! error TS2769: Types of property '1' are incompatible.
!!! error TS2769: Type at position 1 in source is not compatible with type at position 1 in target.
!!! error TS2769: Type 'number' is not assignable to type 'boolean'.
!!! error TS2769: Overload 2 of 3, '(entries?: readonly (readonly [string, boolean])[]): Map<string, boolean>', gave the following error.
!!! error TS2769: Type 'number' is not assignable to type 'boolean'.
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/genericRestParameters2.types
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ f20(42, "hello", ...t3);
>t3 : boolean[]

f20(42, "hello", ...t2, true);
>f20(42, "hello", ...t2, true) : [number, string, string, ...boolean[]]
>f20(42, "hello", ...t2, true) : [number, string, string, ...boolean[], boolean]
>f20 : <T extends unknown[]>(...args: T) => T
>42 : 42
>"hello" : "hello"
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/genericRestParameters3.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ tests/cases/conformance/types/rest/genericRestParameters3.ts(59,5): error TS2345

let a = bar(10, 20);
let b = bar<CoolArray<number>>(10, 20); // Error
~~
~~~~~~
!!! error TS2345: Argument of type '[10, 20]' is not assignable to parameter of type 'CoolArray<number>'.
!!! error TS2345: Property 'hello' is missing in type '[10, 20]' but required in type 'CoolArray<number>'.
!!! related TS2728 tests/cases/conformance/types/rest/genericRestParameters3.ts:30:5: 'hello' is declared here.
Expand All @@ -133,7 +133,7 @@ tests/cases/conformance/types/rest/genericRestParameters3.ts(59,5): error TS2345
!!! error TS2345: Property 'hello' is missing in type '[number]' but required in type 'CoolArray<unknown>'.
!!! related TS2728 tests/cases/conformance/types/rest/genericRestParameters3.ts:30:5: 'hello' is declared here.
baz(1, 2); // Error
~
~~~~
!!! error TS2345: Argument of type '[number, number]' is not assignable to parameter of type 'CoolArray<unknown>'.
!!! error TS2345: Property 'hello' is missing in type '[number, number]' but required in type 'CoolArray<unknown>'.
!!! related TS2728 tests/cases/conformance/types/rest/genericRestParameters3.ts:30:5: 'hello' is declared here.
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/iterableArrayPattern28.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ tests/cases/conformance/es6/destructuring/iterableArrayPattern28.ts(2,24): error
Type 'IteratorYieldResult<[string, number] | [string, boolean]>' is not assignable to type 'IteratorYieldResult<readonly [string, number]>'.
Type '[string, number] | [string, boolean]' is not assignable to type 'readonly [string, number]'.
Type '[string, boolean]' is not assignable to type 'readonly [string, number]'.
Types of property '1' are incompatible.
Type at position 1 in source is not compatible with type at position 1 in target.
Type 'boolean' is not assignable to type 'number'.
Overload 2 of 3, '(entries?: readonly (readonly [string, number])[]): Map<string, number>', gave the following error.
Type 'boolean' is not assignable to type 'number'.
Expand All @@ -26,7 +26,7 @@ tests/cases/conformance/es6/destructuring/iterableArrayPattern28.ts(2,24): error
!!! error TS2769: Type 'IteratorYieldResult<[string, number] | [string, boolean]>' is not assignable to type 'IteratorYieldResult<readonly [string, number]>'.
!!! error TS2769: Type '[string, number] | [string, boolean]' is not assignable to type 'readonly [string, number]'.
!!! error TS2769: Type '[string, boolean]' is not assignable to type 'readonly [string, number]'.
!!! error TS2769: Types of property '1' are incompatible.
!!! error TS2769: Type at position 1 in source is not compatible with type at position 1 in target.
!!! error TS2769: Type 'boolean' is not assignable to type 'number'.
!!! error TS2769: Overload 2 of 3, '(entries?: readonly (readonly [string, number])[]): Map<string, number>', gave the following error.
!!! error TS2769: Type 'boolean' is not assignable to type 'number'.
24 changes: 12 additions & 12 deletions tests/baselines/reference/optionalTupleElements1.errors.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
tests/cases/conformance/types/tuple/optionalTupleElements1.ts(11,29): error TS1257: A required element cannot follow an optional element.
tests/cases/conformance/types/tuple/optionalTupleElements1.ts(15,5): error TS2322: Type 'T2' is not assignable to type 'T1'.
Property '2' is optional in type '[number, string, (boolean | undefined)?]' but required in type '[number, string, boolean]'.
Source provides no match for required element at position 2 in target.
tests/cases/conformance/types/tuple/optionalTupleElements1.ts(16,5): error TS2322: Type 'T3' is not assignable to type 'T1'.
Property '1' is optional in type '[number, (string | undefined)?, (boolean | undefined)?]' but required in type '[number, string, boolean]'.
Source provides no match for required element at position 1 in target.
tests/cases/conformance/types/tuple/optionalTupleElements1.ts(17,5): error TS2322: Type 'T4' is not assignable to type 'T1'.
Property '0' is optional in type '[(number | undefined)?, (string | undefined)?, (boolean | undefined)?]' but required in type '[number, string, boolean]'.
Source provides no match for required element at position 0 in target.
tests/cases/conformance/types/tuple/optionalTupleElements1.ts(20,5): error TS2322: Type 'T3' is not assignable to type 'T2'.
Property '1' is optional in type '[number, (string | undefined)?, (boolean | undefined)?]' but required in type '[number, string, (boolean | undefined)?]'.
Source provides no match for required element at position 1 in target.
tests/cases/conformance/types/tuple/optionalTupleElements1.ts(21,5): error TS2322: Type 'T4' is not assignable to type 'T2'.
Property '0' is optional in type '[(number | undefined)?, (string | undefined)?, (boolean | undefined)?]' but required in type '[number, string, (boolean | undefined)?]'.
Source provides no match for required element at position 0 in target.
tests/cases/conformance/types/tuple/optionalTupleElements1.ts(25,5): error TS2322: Type 'T4' is not assignable to type 'T3'.
Property '0' is optional in type '[(number | undefined)?, (string | undefined)?, (boolean | undefined)?]' but required in type '[number, (string | undefined)?, (boolean | undefined)?]'.
Source provides no match for required element at position 0 in target.


==== tests/cases/conformance/types/tuple/optionalTupleElements1.ts (7 errors) ====
Expand All @@ -33,32 +33,32 @@ tests/cases/conformance/types/tuple/optionalTupleElements1.ts(25,5): error TS232
t1 = t2; // Error
~~
!!! error TS2322: Type 'T2' is not assignable to type 'T1'.
!!! error TS2322: Property '2' is optional in type '[number, string, (boolean | undefined)?]' but required in type '[number, string, boolean]'.
!!! error TS2322: Source provides no match for required element at position 2 in target.
t1 = t3; // Error
~~
!!! error TS2322: Type 'T3' is not assignable to type 'T1'.
!!! error TS2322: Property '1' is optional in type '[number, (string | undefined)?, (boolean | undefined)?]' but required in type '[number, string, boolean]'.
!!! error TS2322: Source provides no match for required element at position 1 in target.
t1 = t4; // Error
~~
!!! error TS2322: Type 'T4' is not assignable to type 'T1'.
!!! error TS2322: Property '0' is optional in type '[(number | undefined)?, (string | undefined)?, (boolean | undefined)?]' but required in type '[number, string, boolean]'.
!!! error TS2322: Source provides no match for required element at position 0 in target.
t2 = t1;
t2 = t2;
t2 = t3; // Error
~~
!!! error TS2322: Type 'T3' is not assignable to type 'T2'.
!!! error TS2322: Property '1' is optional in type '[number, (string | undefined)?, (boolean | undefined)?]' but required in type '[number, string, (boolean | undefined)?]'.
!!! error TS2322: Source provides no match for required element at position 1 in target.
t2 = t4; // Error
~~
!!! error TS2322: Type 'T4' is not assignable to type 'T2'.
!!! error TS2322: Property '0' is optional in type '[(number | undefined)?, (string | undefined)?, (boolean | undefined)?]' but required in type '[number, string, (boolean | undefined)?]'.
!!! error TS2322: Source provides no match for required element at position 0 in target.
t3 = t1;
t3 = t2;
t3 = t3;
t3 = t4; // Error
~~
!!! error TS2322: Type 'T4' is not assignable to type 'T3'.
!!! error TS2322: Property '0' is optional in type '[(number | undefined)?, (string | undefined)?, (boolean | undefined)?]' but required in type '[number, (string | undefined)?, (boolean | undefined)?]'.
!!! error TS2322: Source provides no match for required element at position 0 in target.
t4 = t1;
t4 = t2;
t4 = t3;
Expand Down
29 changes: 15 additions & 14 deletions tests/baselines/reference/restTupleElements1.errors.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
tests/cases/conformance/types/tuple/restTupleElements1.ts(3,22): error TS1257: A required element cannot follow an optional element.
tests/cases/conformance/types/tuple/restTupleElements1.ts(8,13): error TS1256: A rest element must be last in a tuple type.
tests/cases/conformance/types/tuple/restTupleElements1.ts(9,13): error TS2574: A rest element type must be an array type.
tests/cases/conformance/types/tuple/restTupleElements1.ts(10,13): error TS2574: A rest element type must be an array type.
tests/cases/conformance/types/tuple/restTupleElements1.ts(10,16): error TS8020: JSDoc types can only be used inside documentation comments.
tests/cases/conformance/types/tuple/restTupleElements1.ts(23,31): error TS2344: Type 'number[]' does not satisfy the constraint '[number, ...number[]]'.
Property '0' is optional in type 'number[]' but required in type '[number, ...number[]]'.
Source provides no match for required element at position 0 in target.
tests/cases/conformance/types/tuple/restTupleElements1.ts(24,31): error TS2344: Type '[]' does not satisfy the constraint '[number, ...number[]]'.
Source has 0 element(s) but target requires 1.
tests/cases/conformance/types/tuple/restTupleElements1.ts(29,18): error TS2344: Type 'number[]' does not satisfy the constraint '[number]'.
Expand All @@ -16,16 +15,18 @@ tests/cases/conformance/types/tuple/restTupleElements1.ts(32,31): error TS2344:
tests/cases/conformance/types/tuple/restTupleElements1.ts(33,31): error TS2344: Type '[string, ...number[]]' does not satisfy the constraint '[number, ...number[]]'.
Type 'string' is not assignable to type 'number'.
tests/cases/conformance/types/tuple/restTupleElements1.ts(34,31): error TS2344: Type '[number, number, string]' does not satisfy the constraint '[number, ...number[]]'.
Types of property '2' are incompatible.
Type 'string' is not assignable to type 'number'.
Type at positions 1 through 2 in source is not compatible with type at position 1 in target.
Type 'string | number' is not assignable to type 'number'.
Type 'string' is not assignable to type 'number'.
tests/cases/conformance/types/tuple/restTupleElements1.ts(35,31): error TS2344: Type '[number, number, number, string]' does not satisfy the constraint '[number, ...number[]]'.
Types of property '3' are incompatible.
Type 'string' is not assignable to type 'number'.
Type at positions 1 through 3 in source is not compatible with type at position 1 in target.
Type 'string | number' is not assignable to type 'number'.
Type 'string' is not assignable to type 'number'.
tests/cases/conformance/types/tuple/restTupleElements1.ts(59,4): error TS2345: Argument of type '[]' is not assignable to parameter of type '[unknown, ...unknown[]]'.
Source has 0 element(s) but target requires 1.


==== tests/cases/conformance/types/tuple/restTupleElements1.ts (14 errors) ====
==== tests/cases/conformance/types/tuple/restTupleElements1.ts (13 errors) ====
type T00 = [string?];
type T01 = [string, string?];
type T02 = [string?, string]; // Error
Expand All @@ -36,8 +37,6 @@ tests/cases/conformance/types/tuple/restTupleElements1.ts(59,4): error TS2345: A
type T05 = [...[...[...string[]]]];
type T06 = [string, ...string[]];
type T07 = [...string[], string]; // Error
~~~~~~~~~~~
!!! error TS1256: A rest element must be last in a tuple type.
type T08 = [...string]; // Error
~~~~~~~~~
!!! error TS2574: A rest element type must be an array type.
Expand All @@ -61,7 +60,7 @@ tests/cases/conformance/types/tuple/restTupleElements1.ts(59,4): error TS2345: A
assign<[number, ...number[]], number[]>(); // Error
~~~~~~~~
!!! error TS2344: Type 'number[]' does not satisfy the constraint '[number, ...number[]]'.
!!! error TS2344: Property '0' is optional in type 'number[]' but required in type '[number, ...number[]]'.
!!! error TS2344: Source provides no match for required element at position 0 in target.
assign<[number, ...number[]], []>(); // Error
~~
!!! error TS2344: Type '[]' does not satisfy the constraint '[number, ...number[]]'.
Expand Down Expand Up @@ -90,13 +89,15 @@ tests/cases/conformance/types/tuple/restTupleElements1.ts(59,4): error TS2345: A
assign<[number, ...number[]], [number, number, string]>(); // Error
~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2344: Type '[number, number, string]' does not satisfy the constraint '[number, ...number[]]'.
!!! error TS2344: Types of property '2' are incompatible.
!!! error TS2344: Type 'string' is not assignable to type 'number'.
!!! error TS2344: Type at positions 1 through 2 in source is not compatible with type at position 1 in target.
!!! error TS2344: Type 'string | number' is not assignable to type 'number'.
!!! error TS2344: Type 'string' is not assignable to type 'number'.
assign<[number, ...number[]], [number, number, number, string]>(); // Error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2344: Type '[number, number, number, string]' does not satisfy the constraint '[number, ...number[]]'.
!!! error TS2344: Types of property '3' are incompatible.
!!! error TS2344: Type 'string' is not assignable to type 'number'.
!!! error TS2344: Type at positions 1 through 3 in source is not compatible with type at position 1 in target.
!!! error TS2344: Type 'string | number' is not assignable to type 'number'.
!!! error TS2344: Type 'string' is not assignable to type 'number'.

type T20 = [number, string, ...boolean[]];

Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/restTupleElements1.types
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ type T21 = T20[0];
>T21 : number

type T22 = T20[0 | 1];
>T22 : T22
>T22 : string | number

type T23 = T20[0 | 1 | 2];
>T23 : string | number | boolean
Expand Down
Loading