javascript - Se till att arrayen har alla typer från en union
Säg att jag har en union som ser ut så här
type Colors = 'red' | 'blue' | 'pink'
Är det möjligt att typkontrollera en array mot denna union och se till att arrayen innehåller alla typerna?
D.v.s.:
const colors: UnionToTuple<Colors> = ['red', 'blue'] // type error, missing 'pink'
const colors: UnionToTuple<Colors> = ['red', 'blue', 'pink'] // no error
Svar #1
Genom att ta idéer från detta svar kan du skapa en funktion som typkontrollerar genom att använda en typparameter för den passerade arrayen, T. Typa den som T extends Colors[] för att säkerställa att varje objekt i arrayen finns i Colors, och typa den också som [Colors] extends [T[number]] ? unknown : 'Invalid' för att säkerställa att varje objekt av typen Colors finns i den passerade arrayen:
type Colors = 'red' | 'blue' | 'pink';
const arrayOfAllColors = <T extends Colors[]>(
array: T & ([Colors] extends [T[number]] ? unknown : 'Invalid')
) => array;
const missingColors = arrayOfAllColors(['red', 'blue']); // error
const goodColors = arrayOfAllColors(['red', 'blue', 'pink']); // compiles
const extraColors = arrayOfAllColors(['red', 'blue', 'pink', 'bad']); // error
Mer generellt, omslut det i en annan funktion så att du kan skicka och använda en typparameter av unionstypen:
type Colors = 'red' | 'blue' | 'pink';
const arrayOfAll = <T>() => <U extends T[]>(
array: U & ([T] extends [U[number]] ? unknown : 'Invalid')
) => array;
const arrayOfAllColors = arrayOfAll<Colors>();
const missingColors = arrayOfAllColors(['red', 'blue']); // error
const goodColors = arrayOfAllColors(['red', 'blue', 'pink']); // compiles
const extraColors = arrayOfAllColors(['red', 'blue', 'pink', 'bad']); // error
Svar #2
Lösningen från @CertainPerformance avvisar inte tomma arrayer. Här är en lösning:
const arrayOfAll = <T>() => <U extends T[]>(
array: U & ([T] extends [U[number]] ? unknown : 'Invalid') & { 0:T }
) => array;
