-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Closed
Labels
Breaking ChangeWould introduce errors in existing codeWould introduce errors in existing codeFixedA PR has been merged for this issueA PR has been merged for this issueSuggestionAn idea for TypeScriptAn idea for TypeScript
Milestone
Description
Update: converted to proposal.
Background
Currently, tuples are arrays that are restricted in minimum length, but not in maximum:
var t1: [number, number] = [1]; // this doesn't work
var t2: [number] = [1, 2]; // this works
This makes harder to predict types or errors in some scenarios:
var t1: [number, string];
var t2 = [...t1, ...t1]; // could be inferred to be [number, string, number, string], but must be inferred as [number, string] (now it's simply inferred as (number|string)[])
var t3: [number, string] = [1, "a"];
t3[2]; // ok, but must be an error
There also might be difficult to adopt variadic kinds, especially in type construction:
function f<...T>(...rest: [...T]): [...T, ...T] {
var rest1: [...T] = [...rest, 1]; // it will be acceptable due to current rules
return [...rest1, ...rest1]; // due to types it seems to be [...T, ...T], but actually is [...T, number, ...T, number]
}
Proposal
(1) Restrict tuple instance to match exact length
var t1: [number, string] = [1, "a"]; // ok
var t2: [number, string] = [1]; // error (existing)
var t3: [number, string] = [1, "a", "b"]; // error (new)
(2) Introduce open length tuple types
Open-length tuple types will be the same as tuple types are now.
var t1: [number, string, ...] = [1, "a", 2, "b"]; // same as current tuples are now
var t2: [number, string, ...(number|string|boolean)[]]; // explicitly type rest elements -- syntax option 1 -- consistent with rest parameters
var t3: [number, string, ...number|string]; // explicitly type rest elements -- syntax option 2
// strict tuple type can be implicitly converted to open length tuple type
var t4: [number, string, string];
var t5: [number, string, ...] = t4; // ok
var t6: [number, ...] = t4; // error, 'number|string' cannot be converted to 'number'
var t6: [number|string, ...] = t4; // ok
var t7: [number, ...(number|string)[]] = t4; // ok
(3) Improve contextual type inference for spread operators on tuples
var t1: [number, string];
var t2: [number, string, number, string] = [...t1, ...t1]; // it's proven now
var t3: [number, ...];
var t4: [string, ...];
var t4: [number, number|string, ...] = [...t3, ...t4]; // this also can be proven
Related issues
This addresses:
- out of range index in a tuple magically works #5203 - out of range index in a tuple magically works /cc @Aleksey-Bykov @RyanCavanaugh @DanielRosenwasser
- Proposal: Variadic Kinds -- Give specific types to variadic functions #5453 - variadic kinds /cc @sandersn @JsonFreeman
Disadvantages
This is definitely a breaking change.
masaeedu, Igorbek, Meligy, fusepilot, krryan and 27 more
Metadata
Metadata
Assignees
Labels
Breaking ChangeWould introduce errors in existing codeWould introduce errors in existing codeFixedA PR has been merged for this issueA PR has been merged for this issueSuggestionAn idea for TypeScriptAn idea for TypeScript