Skip to content

Incorrect type narrowing for tuples #61332

Closed as not planned
Closed as not planned

Description

@Florian-Mt

🔎 Search Terms

"narrow tuple", "tuple inference"

🕗 Version & Regression Information

This is the behavior in every version I tried in the playground (v3.3, v4.5, v5.8, nightly), and I reviewed the FAQ about "tuple", "narrow", "inference".

⏯ Playground Link

https://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgCrIN4F8BQOED2IAzmMmADbCkBcyA2ugD7IgCuFFANGsi+5wC6yALwMB3VhwqCcAejnIA8gGlkwGOSql1xZAApmUzgEp6wgEZsyIAmRgEo5NgAcKEYjytkAksgC2EHAgyHDObigWEAhwbMQo7iAA5mAAFrrIMMAAHhAAJngwbCAIYMBEyKnBee76lNRgdIw8qIImmDjIXVoNOLg4Ggb1pAB0EABu0ACedaIAfOTIAIQiYhIm7Rid3VUgNRB12mAmfXiDhw30AAzCK2vSyABkjz2k9ACMt6vGFJvbXbt9hdSCdcEA

💻 Code

interface T {}

const tlist: [T | null, T | null] = [null, null]
// OK if tlist is (T | null)[] but not for tuples, but I mean a tuple because length is fixed

function handle(tlist: [T, T]) {
    tlist
}

if (tlist.every(t => t !== null)) {
    handle(tlist)
}

if (tlist[0] !== null && tlist[1] !== null) {
    handle(tlist)
}

🙁 Actual behavior

handle(tlist) throws in the TS compiler:

Argument of type '[T | null, T | null] & T[]' is not assignable to parameter of type '[T, T]'.
  Types of property '0' are incompatible.
    Type 'T | null' is not assignable to type 'T'.
      Type 'null' is not assignable to type 'T'.

🙂 Expected behavior

The condition in both if blocks should narrow tlist to the type [T, T], i.e. no error.

Additional information about the issue

It is OK if tlist is (T | null)[], but not for tuples. However, I really want to use a tuple here because the length of tlist is known and will never change.

Activity

  1. jcalz commented on Mar 3, 2025

    @jcalz
    Contributor

    Your second example is effectively a duplicate of #42384.


    Your first example is a limitation of the type predicates on array methods like every(). You could merge your own call signature to handle tuples also, maybe like

    interface Array<T> {
        every<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any
        ): this is { [I in keyof this]: this[I] & S };
    }

    Playground link

    but I'm sure there are weird edge cases. Curiously I searched but I didn't find any existing issues filed about the type predicate methods on tuples, so maybe this isn't a duplicate of an existing issue? There are near-misses about map() on tuples not producing tuples.

  2. typescript-bot commented on Mar 6, 2025

    @typescript-bot
    Contributor

    This issue has been marked as "Duplicate" and has seen no recent activity. It has been automatically closed for house-keeping purposes.

  3. locked as resolved and limited conversation to collaborators on Oct 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions