Skip to content

Exhaustiveness check fails when matching arrays with 2 or more elements #322

@allan-cannon

Description

@allan-cannon

Describe the bug

This code fails the exhaustiveness check even though all cases have been covered. In this case my intent is to use up to the first 2 strings in an array of unknown length with different handling depending on the number of strings.

const stringList: string[] = [];

match(stringList)
  .with([], () => {})
  .with([P.string], () => {})
  .with([P.string, P.string], () => {})
  .with([P.string, P.string, ...P.array(P.string)], () => {})
  .exhaustive(); // Type 'NonExhaustiveError<[string, ...string[]]>' has no call signatures.

The actual matching appears to be working as expected, just the exhaustiveness check is wrong. For example this code resolves the exhaustiveness check but the last with branch is unreachable.

const stringList: string[] = [];

match(stringList)
  .with([], () => {})
  .with([P.string], () => {})
  .with([P.string, P.string], () => {})
  .with([P.string, P.string, ...P.array(P.string)], () => {})
  .with([P.string, ...P.array(P.string)], () => {}) // This branch is unreachable
  .exhaustive(); // No exhaustiveness error

This code "works" but the type of the second item is string | undefined which is not what I'm looking for.

const stringList: string[] = [];

match(stringList)
  .with([], () => {})
  .with([P.string], () => {})
  .with([P.string, ...P.array(P.string)], ([first, second]) => {}) // second is type string | undefined
  .exhaustive(); // no exhaustiveness error

TypeScript playground with a minimal reproduction case

Playground

Versions

  • TypeScript version: 5.8.3
  • ts-pattern version: 5.7.0
  • environment: chrome

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions