103

在 TypeScript 中,某些类型是使用extends keyofor定义的in keyof。我试图理解它们的意思,但到目前为止我还没有成功。

我得到的是keyof仅返回一个联合类型,该类型具有所有名称作为可能的值,这些名称作为属性名称存在于您在之后指定的类型上keyof

type T = keyof string;

T因此等价于startsWith | endsWith | trim | substring | ...

这个对吗?

现在,如果我试着思考什么extends keyofin keyof意思,我的直觉会说:

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

所以,从这个 POVextends keyof会描述一个>=关系,in keyof会描述一个<=关系。这个对吗?如果不是,什么是正确的?

4

1 回答 1

187

对于任何类型Tkeyof T是 的已知公共属性名称的并集T

例子:

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

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

keyof string因此,您对产量的假设startsWith | endsWith | trim | ...是正确的。您可以在查找类型发行说明中了解有关它的更多信息。

扩展键

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可能如下:

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>

于 2019-08-03T11:57:55.140 回答