microsoft / microsoft/TypeScript

Equivalent Tuple with Rest types not duck-typing properly

Open
#52,496 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Suggestion
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.