Check if a tuple exhausts a union in TypeScript

Published onSeptember 14, 2024
Topicstypescript

When I have a little time to spend in between some tasks, I usually wander on TS-related discord channels and lend a hand in helping channels. Here's a fun question I spent some time solving:

Is it possible to create a type Exhaustive<U, A> that checks that every element of the array A is a constituent of the union U and each constituent of U appears exactly once in A?

Here is my stab at it:

type <,  extends unknown[]> = [] extends [never] 
  ?  extends []
    ? true
    : false
  :  extends [infer , ...infer ]
  ?  extends 
    ? <<, >, >
    : false
  : false;

As the name suggests, we have to exhaust all the possible pairs U-A, so we're going to recursively check them all by removing the pairs from subsequent checks, until the array is empty and the union is never.

// Basic case
type  = <'a'|'b'|'c', ['a','b','c']>


// Union and tuple have different order
type  = <'a'|'b'|'c', ['b','c','a']>


// Duplicate element in array
type  = <'a'|'b'|'c', ['a','a','b','c']>


// Shorter array
type  = <'a'|'b'|'c', ['a','b']>


// Shorter tuple
type  = <'a'|'b', ['a','b','c']>

While I don't know what use case this might serve (the original poster didn't mention it), this was a fun challenge nonetheless.