github gvergnaud/ts-pattern v2.4.0

latest releases: v5.5.0, v5.4.0, v5.3.1...
3 years ago

Support for when predicate with .exhaustive()

when(predicate) patterns and match(...).when(predicate) are now permitted within .exhaustive() match expressions.

If your predicate is a type guard function, the case will be considered handled:

type Input = 'a' | 'b'

match<Input>('a')
  .exhaustive()
  .when((x): x is 'a' => x === 'a' , () => {...})
  .when((x): x is 'b' => x === 'b' , () => {...})
  // This compiles
  .run();


match<Input>('a')
  .exhaustive()
  .when((x): x is 'a' => x === 'a' , () => {...})
  // This doesn't compiles
  .run();

But if your predicate isn't a type guard, exhaustive checking will consider that this clause never matches anything:

match<Input>('a')
  .exhaustive()
  .when((x): x is 'a' => x === 'a' , () => {...})
  .when(x => x === 'b' , () => {...})
  // This doesn't compiles, because ts-pattern has no way to know that the 'b' case is handled
  .run();

It works similarily with the when() helper function:

type input = { type: 'success', data: string[] } | { type: 'error' }

match(input)
  .exhaustive()
  .with({ type: 'success', data: when(xs => xs.length > 0) }, () => {...})
  .with({ type: 'error' }, () => {...})
  // this doesn't compile, { type: 'success' } with an empty data array is not handled
  .run();


match(input)
  .exhaustive()
  .with({ type: 'success', data: when(xs => xs.length > 0) }, () => {...})
  .with({ type: 'success' }, () => {...})
  .with({ type: 'error' }, () => {...})
  // this compiles
  .run();

Don't miss a new ts-pattern release

NewReleases is sending notifications on new releases.