I would like to declare a type that requires all the keys of a given type T
to be included in an array, e.g.:
checkKeys<T>(arr: Array<keyof T>): void {
// do something
}
interface MyType {
id: string;
value: number;
}
Currently if a call checkKeys<MyType>
, TS will consider the value passed as valid if it contains any key of MyType
(id | value
):
checkKeys<MyType>(['id', 'value']); // valid
checkKeys<MyType>(['id']); // valid
checkKeys<MyType>(['id', 'values']); // invalid
Is it possible to require that all keys are specified in the array?
You can't do that with an array type (at least I am not aware of a way to spread the union of keys into a tuple type, there may be one I'm just not aware of it). An alternative would be to use an object literal to achieve a similar effect. The syntax is a bit more verbose but the compiler will validate that only the correct keys are specified. We will use the Record
mapped type and we can use the 0
literal types for values as only the keys matter.
function checkKeys<T>(o: Record<keyof T, 0>): void {
// do something
}
interface MyType {
id: string;
value: number;
}
checkKeys<MyType>({ id: 0, value: 0 }); // valid
checkKeys<MyType>({ id: 0 }); // invalid
checkKeys<MyType>({ id: 0, values: 0 }); // invalid