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 
type T1 = true
T1
= <'a'|'b'|'c', ['a','b','c']>
// Union and tuple have different order type
type T2 = true
T2
= <'a'|'b'|'c', ['b','c','a']>
// Duplicate element in array type
type T3 = false
T3
= <'a'|'b'|'c', ['a','a','b','c']>
// Shorter array type
type T4 = false
T4
= <'a'|'b'|'c', ['a','b']>
// Shorter tuple type
type T5 = false
T5
= <'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.