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 keyofextends, 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 keyofin 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!