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