microsoft / microsoft/TypeScript
Equivalent Tuple with Rest types not duck-typing properly
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 111k
- Forks
- 14.3k
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 117
Description
Bug Report
A tuple type with a rest element doesn't duck-type properly to the similar tuple type, although they are conceptually identical, causing a ts2345 error to show up when trying to use one with the other.
The type I tested was a type defining a non-empty array. It looks like there's a bug because the location of the "non-empty item" in the definition matters for typescript, although there shouldn't be any difference in the kind of arrays that are accepted for each type.
🔎 Search Terms
- tuple
- rest
🕗 Version & Regression Information
Since 4.2 where rest params where allowed a the start of a tuple too
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about tuple
⏯ Playground Link
Playground link with relevant code
💻 Code
type FirstItem<T> = [T, ...T[]];
type LastItem<T> = [...T[], T];
const f0: FirstItem<number> = []
const l0: LastItem<number> = []
const f1: FirstItem<number> = [1]
const l1: LastItem<number> = [1]
const f2: FirstItem<number> = [1, 2]
const l2: LastItem<number> = [1, 2]
function foo(x: FirstItem<number>): void {
// DO NOTHING
}
foo(f2) // OK
foo(l2) // ts2345
const x: number[] = [2, 3, 4]
foo([1, ...x]) // OK
foo([...x, 5]) // ts2345
🙁 Actual behavior
- ts2345 is shown
🙂 Expected behavior
- the two types should be considered equivalent and duck-typeable.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the Playground link and the reduced TypeScript example comparing FirstItem and LastItem. Trace tuple rest-element assignability and the ts2345 diagnostic for foo(l2) and foo([...x, 5]). Done means equivalent non-empty tuple types are accepted interchangeably without regressing the existing tuple checks.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100