In TypeScript, what do “extends keyof” and “in keyof” mean?

落花浮王杯 提交于 2020-06-10 05:18:07

问题


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 from T, i.e. it has all these possible values, but maybe more.
  • in keyof is any type that takes values from T, 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!