Skip to content

Proposal: strict and open-length tuple types #6229

Description

Update: converted to proposal.

Background

Currently, tuples are arrays that are restricted in minimum length, but not in maximum:

vart1: [number,number]=[1];// this doesn't workvart2: [number]=[1,2];// this works

This makes harder to predict types or errors in some scenarios:

vart1: [number,string];vart2=[...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)[])vart3: [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:

functionf<...T>(...rest: [...T]): [...T, ...T]{varrest1: [...T]=[...rest,1];// it will be acceptable due to current rulesreturn[...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

vart1: [number,string]=[1,"a"];// okvart2: [number,string]=[1];// error (existing)vart3: [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.

vart1: [number,string, ...]=[1,"a",2,"b"];// same as current tuples are nowvart2: [number,string, ...(number|string|boolean)[]];// explicitly type rest elements -- syntax option 1 -- consistent with rest parametersvart3: [number,string, ...number|string];// explicitly type rest elements -- syntax option 2// strict tuple type can be implicitly converted to open length tuple typevart4: [number,string,string];vart5: [number,string, ...]=t4;// okvart6: [number, ...]=t4;// error, 'number|string' cannot be converted to 'number'vart6: [number|string, ...]=t4;// okvart7: [number, ...(number|string)[]]=t4;// ok

(3) Improve contextual type inference for spread operators on tuples

vart1: [number,string];vart2: [number,string,number,string]=[...t1, ...t1];// it's proven nowvart3: [number, ...];vart4: [string, ...];vart4: [number,number|string, ...]=[...t3, ...t4];// this also can be proven

Related issues

This addresses:

Disadvantages

This is definitely a breaking change.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Breaking ChangeWould introduce errors in existing codeFixedA PR has been merged for this issueSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions