问题
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 😉
What I got is that keyof
alone returns a union type which has all the names as possible values that are existent as property names on the type that you specify after keyof
.
type T = keyof string;
T
therefor is equivalent to startsWith | endsWith | trim | substring | ...
.
Is this correct?
Now, if I try to think about what extends keyof
and in keyof
mean, my gut feeling says the following:
extends keyof
is any type that derives fromT
, i.e. it has all these possible values, but maybe more.in keyof
is any type that takes values fromT
, but not necessarily all of them (it's possible, but maybe less).
So, from this POV extends keyof
would describe a >=
relation, in keyof
would describe a <=
relation. Is this correct? If not, what would be correct?
回答1:
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.
Your assumption about extends keyof
is not correct though. extends
, in this case, is used to define the type of a generic parameter, e.g. <T, K extends keyof T>
. It has nothing to do with extending a type or inheritance, contrary to extending interfaces.
A usage of extends keyof
could be the following:
interface IAnimal {
extinct: boolean;
race: string;
}
function getKeyValue<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}
const animal: IAnimal = {
extinct: false,
race: "dog"
};
const animalRace = getKeyValue(animal, "race"); // race is a key of IAnimal -> works
const animalAge = getKeyValue(animal, "age"); // age is not a key of IAnimal -> fails
Aside from the documentation, I found this article helpful.
Your assumption about in keyof
is also incorrect. in
does not describes a <=
relationship, it is used when we're defining an indexer property that we want to type with specific keys.
We could for example use it to create a new type that re-maps all properties of an existing type to be optional:
type Optional<T> = { [K in keyof T]?: T[K] };
const animal: Optional<IAnimal> = {
extinct: true
};
Aside from the documentation, I once again found this article helpful.
来源:https://stackoverflow.com/questions/57337598/in-typescript-what-do-extends-keyof-and-in-keyof-mean