在TypeScript中,“extends keyof”和“in keyof”是什么意思?

160
在TypeScript中,一些类型使用extends keyofin keyof进行定义。我试图理解它们的含义,但到目前为止我还没有成功。
我了解到keyof单独返回一个联合类型,其中包含所有可能的名称作为值,这些名称存在于keyof之后指定的类型的属性名称上。
type T = keyof string;

T 即等同于 startsWith | endsWith | trim | substring | ...

这个表述正确吗?

现在,如果我试着思考 extends keyofin keyof 的含义,我的直觉告诉我以下内容:

  • extends keyof 是任何从 T 派生出来的类型,即它具有所有这些可能的值,但也可能更多。
  • in keyof 是任何取值自 T 的类型,但不一定是所有的值(也可能是部分值)。

所以,从这个角度来看,extends keyof 将描述一个 >= 关系,in keyof 将描述一个 <= 关系。这个表述是否正确?如果不正确,应该如何修正?

1个回答

281

对于任何类型Tkeyof TT已知的、公共属性名称的联合。

例如:

interface Person {
  age: number;
  name: string;
}

type PersonKeys = keyof Person; // "age" | "name"

你认为keyof string产生的结果是startsWith | endsWith | trim | ...,这一点是正确的。你可以在查找类型发布说明中了解更多相关信息。

extends keyof

extends在这种情况下用于约束泛型参数的类型。例如: <T, K extends keyof T> 因此K只能是T的公共属性名称。与扩展接口相反,它与扩展类型或继承无关。 extends keyof的一个使用示例如下:
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

const person: Person = {
  age: 22,
  name: "Tobias",
};

// name is a property of person
// --> no error
const name = getProperty(person, "name");

// gender is not a property of person
// --> error
const gender = getProperty(person, "gender");

除了关于索引类型的文档,我还发现了这篇有用的文章

in keyof

in 用于定义我们想要使用字符串、数字或符号字面量联合类型进行类型化的 索引签名。结合 keyof 使用,我们可以创建所谓的映射类型,重新映射原始类型的所有属性。

使用 in keyof 的示例如下:

type Optional<T> = { 
  [K in keyof T]?: T[K] 
};

const person: Optional<Person> = {
  name: "Tobias"
  // notice how I do not have to specify an age, 
  // since age's type is now mapped from 'number' to 'number?' 
  // and therefore becomes optional
};

除了映射类型的文档,我又发现了这篇有用的文章

趣闻:我们刚刚构建的Optional<T>类型与官方Partial<T>实用程序类型具有相同的签名!


22
谢谢你的问题。我卡在“ extends keyof”这个概念上了。对于这种情况,他们真的应该选择一个不同的关键字。这真的很令人困惑和反直觉。根据文档,当我们看到“T extends Lengthwise”和“K extends keyof T”时,“extends”关键字实际上意味着完全不同的东西。 - cbdeveloper
3
这是否意味着extends始终用于泛型,而in始终用于索引访问器? - Junle Li
3
@JunleLi 是的,你不能反过来使用它们。抱歉回复晚了,我好像错过了你的评论! - Tobias Tengler
1
@cbdeveloper A extends B 的意思是 "某个 AB 的子类型"。如果 B 是一个键类型,则 A 是集合中的一个字符串,由于索引访问类型,类型检查器可以更多地了解使用此字符串的代码。 - Ben Greenman
3
比起非常棒的官方手册,这份解释更清晰易懂。 - ChrisCrossCrash
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接