Controllare se una tupla esaurisce un'unione in TypeScript

Pubblicato il14 settembre 2024
Argomentitypescript

Nei tempi morti tra un task e l'altro, solitamente girovago tra i vari server di discord dedicati a TypeScript e do una mano nei canali d'aiuto. Questa è una domanda interessante che mi è capitata tra le mani:

È possibile creare un tipo Exhaustive<U,A> che controlli che ogni elemento dell'array A sia costitutivo dell'unione U e ogni costitutivo di U compaia esattamente una volta in A?

Ecco il mio tentativo:

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

Come suggerisce il nome, dobbiamo esaurire tutte le possibili coppie di elementi U-A, quindi le controlliamo tutte in maniera ricorsiva, rimuovendo le coppie già controllate ad ogni passo, fino a che l'array è vuoto e l'unione è 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']>

Non so quale possa essere il caso d'uso di un tipo del genere (chi ha posto la domanda non l'ha specificato), ma è stata comunque una sfida divertente.