Say I have a union that looks like this
type Colors = 'red' | 'blue' | 'pink'
Is it possible to type check an array against this union and make sure the array contains all of the types?
I.e.:
const colors: UnionToTuple<Colors> = ['red', 'blue'] // type error, missing 'pink'
const colors: UnionToTuple<Colors> = ['red', 'blue', 'pink'] // no error
Taking ideas from this answer, you can make a function that type-checks by using a type parameter of the passed array, T. Type it as T extends Colors[]
to make sure every item of the array is in Colors
, and also type it as [Colors] extends [T[number]] ? unknown : 'Invalid'
to make sure every item of the Colors type is in the passed array:
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
More generically, wrap it in another function so you can pass and use a type parameter of the union type:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With