gvergnaud/ts-pattern

Set exhaustive not working on type level?

darky opened this issue · 1 comments

darky commented

Describe the bug
Trying to exhaustive Set, but seems it's not working on type level

Code Sandbox with a minimal reproduction case

const s = new Set<'a' | 'b'>(['a']);

match(s)
  .with(P.set('a'), () => 123)
  .with(P.set('b'), () => 123)
  .exhaustive();
  
// This expression is not callable.
//  Type 'NonExhaustiveError<Set<"a" | "b">>' has no call signatures.ts(2349)

Versions

  • TypeScript version: 5.2.2
  • ts-pattern version: 5.0.5
  • environment: node 20.4.0

First, Set<'a' | 'b'> means that each of the Set's elements must satisfy 'a' | 'b', not that the whole Set must satisfy only one of them. For example, Set<number | string> is a Set of numbers and strings.

Second, P.set(subpattern) only matches if all the elements match the sub pattern. Because of this, you have handled the case of a Set with the value 'a' and a Set with the value 'b', not the case of a Set with both.

Depending what you're trying to achieve, you could add the case for both, using a ts-pattern union. However, the possibilities explode exponentially as you add more potential elements.
Or, you could change the declaration of the Set to const s: Set<'a'> | Set<'b'> = new Set(['a']). This of course limits you to a Set with only one element, which doesn't make much sense.

This seems like a very contrived example (and possibly an XY problem), so I'm not sure what exactly you're actually trying to achieve.

TypeScript Playground