Is there a way to require array elements with typescript so that I can do have
type E = keyof T; // Number of properties in T is unknown
let T
I have a solution for enforcing at compile-time that an array contains all values of some arbitrary type T
. That's quite close to what you want - it's missing the check to prevent duplicates - but some people may not need to prevent duplicates (e.g. another question marked as a duplicate of this one doesn't have that requirement).
The NoRepeats
type from @jcalz's answer can probably be combined with this one if you want to enforce that additional requirement.
We can enforce that an array contains every value of type T
by writing a generic function with two type parameters. T
is an arbitrary type, and A
is the type of the array. We want to check that T[]
and A
are identical. A nice way to do this is to write a conditional type which resolves to never
if these two types are not subtypes of each other:
type Equal = [S, T] extends [T, S] ? S : never;
We want to specify the type parameter T
explicitly, to tell the compiler what to check for, but we want A
to be inferred from the actual value, so that the check is meaningful. Typescript doesn't allow specifying some but not all type parameters of a function, but we can get around this with currying:
function allValuesCheck(): (arr: Equal) => T[] {
return arr => arr;
}
Then, this function can be used to ask the compiler to check that an array literal contains all possible values of an arbitrary type:
type Foo = 'a' | 'b';
// ok
const allFoo = allValuesCheck()(['a', 'b']);
// type error
const notAllFoo = allValuesCheck()(['a']);
// type error
const someNotFoo = allValuesCheck()(['a', 'b', 'c']);
The downside is that the type errors are not informative; the first error message just says Type 'string' is not assignable to type 'never'
, and the second error message just says Type 'string' is not assignable to type 'Foo'
. So although the compiler informs you of the error, it doesn't tell you which one is missing or erroneous.
Playground Link