In TypeScript, some types are defined using extends keyof
or in keyof
. I have tried to understand what they mean, but so far I didn\'t succeed
For any type T
, keyof T
is the union of known, public property names of T
.
Your assumption that keyof string
yields startsWith | endsWith | trim | ...
is therefor correct. You can learn more about it here.
extends keyof
extends
, in this case, is used to constrain the type of a generic parameter. Example:
<T, K extends keyof T>
K
can therefor only be a public property name of T
. It has nothing to do with extending a type or inheritance, contrary to extending interfaces.
An usage of extends keyof
could be the following:
interface Animal {
extinct: boolean;
race: string;
}
function setValue<T, K extends keyof T>(obj: T, key: K, value: T[K]) {
obj[key] = value;
}
const huntsman: Animal = {
extinct: false,
race: "spider"
};
// true is a boolean value and matches the type of the "extinct" property
// --> no error
setValue(huntsman, "extinct", true);
// 100 is a number value and does not match the type of the "extinct" property
// --> error
setValue(huntsman, "extinct", 100);
Aside from the documentation, I found this article helpful.
in keyof
in
is used when we're defining an index signature that we want to type with a union of string, number or symbol literals. In combination with keyof
we can use it to create a so called mapped type, which re-maps all properties of the original type.
An usage of in keyof
could be the following:
type Optional<T> = {
[K in keyof T]?: T[K]
};
const animal: Optional<Animal> = {
extinct: true
};
Aside from the documentation, I once again found this article helpful.
Fun fact: The Optional<T>
type we've just built has the same signature as the official Partial<T> utility type!