1

查看此 URL https://www.typescriptlang.org/docs/handbook/advanced-types.html上的 Typescript 文档

type FunctionPropertyNames<T> = {
  [K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];

有人可以向我解释一下右括号后的 [keyof T] 是什么意思吗?这种语法有任何文档吗?

4

3 回答 3

0

这就是所谓的“查找类型”。

  1. keyof X返回一个类型的所有键

  2. 如果

    interface a {
       foo: never
       bar: string
       baz: number
    }

那么type not_here = a['foo']将是never

但是查找类型也支持传入keyof Something,所以

a[keyof a]将是所有类型的as 键/属性的联合,即never | string | number. 虽然never那里没有任何意义,所以 TS 会自动忽略它,导致string | number.

(当然可以a[keyof b],这里没有限制)

我发现找出像这样的复杂类型的最佳方法是像我在这里所做的那样按步骤分解它们:

interface test {
    a: string
    b: () => void
    c: () => void
}

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

type T_B<T> = {
  [K in keyof T]: T[K] extends Function ? K : never;
};

type T_C<T> = {
  [K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];

type a = T_A<test>
type b = T_B<test>
type c = T_C<test>

有了这个,您可以看到为获得所需结果所采取的各个步骤,即“函数类型的键的联合”。

于 2021-01-04T16:39:50.100 回答
0

keyof T表示该T类型的有效键(您可能知道这一点)。当您拥有[x]接口或联合类型时,它会选择名称为 的属性/成员的类型x。例如(游乐场链接):

interface Example {
    a: number;
    b: string;
}
type E1 = Example["a"];
/*
type E1 = number;
*/

据我所知,这些“查找类型”仅记录在此处的 TypeScript 2.1 发行说明中:

keyof和查找类型 在 JavaScript 中,将属性名称作为参数的 API 相当普遍,但到目前为止,还无法表达这些 API 中出现的类型关系。

输入索引类型查询或keyof;索引类型查询keyof T产生 T 允许的属性名称的类型。keyof T类型被认为是字符串的子类型。

例子

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

type K1 = keyof Person; // "name" | "age" | "location"
type K2 = keyof Person[]; // "length" | "push" | "pop" | "concat" | ...
type K3 = keyof { [x: string]: Person }; // string

其双重属性是索引访问类型,也称为查找类型。从语法上讲,它们看起来与元素访问完全一样,但写成类型:

例子

type P1 = Person["name"]; // string
type P2 = Person["name" | "age"]; // string | number
type P3 = string["charAt"]; // (pos: number) => string
type P4 = string[]["push"]; // (...items: string[]) => number
type P5 = string[][0]; // string

您可以将此模式与类型系统的其他部分一起使用,以获取类型安全的查找。

function getProperty<T, K extends keyof T>(obj: T, key: K) {
  return obj[key]; // Inferred type is T[K]
}

function setProperty<T, K extends keyof T>(obj: T, key: K, value: T[K]) {
  obj[key] = value;
}

let x = { foo: 10, bar: "hello!" };

let foo = getProperty(x, "foo"); // number
let bar = getProperty(x, "bar"); // string

let oops = getProperty(x, "wargarbl"); // Error! "wargarbl" is not "foo" | "bar"

setProperty(x, "foo", "string"); // Error!, string expected number

的主要部分为所有非函数类型的属性FunctionPropertyNames<T>生成一个带有never类型成员的接口T,并为那些是原始成员类型生成一个接口。例如,如示例中所示,如果您这样做:

interface Part {
  id: number;
  name: string;
  subparts: Part[];
  updatePart(newName: string): void;
}

type T1 = FunctionPropertyNames<Part>;

T1最终是"updatePart"因为这是T( Part) 中唯一具有函数类型的键。如果没有[keyof T]部分,您将获得与never成员的界面(游乐场链接):

type FunctionPropertyNames<T> = {
  [K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];
type Example<T> = {
  [K in keyof T]: T[K] extends Function ? K : never;
}/* Same as above, but without [keyof T] here*/;

interface Part {
  id: number;
  name: string;
  subparts: Part[];
  updatePart(newName: string): void;
}

type T1 = FunctionPropertyNames<Part>;
/*
type T1 = "updatePart"
*/
type E1 = Example<Part>;
/*
type E1 = {
    id: never;
    name: never;
    subparts: never;
    updatePart: "updatePart";
}
*/

它是提供函数类型属性名称[keyof T]的部分,而不是函数类型属性本身(和类型属性)。FunctionPropertyNamesnever

于 2021-01-04T16:40:36.003 回答
0

这个 [keyof T] 表示 T 中的任何属性。

为了更好地理解,请采取以下措施:

type AB = {
  aa: number,
  ab: () => number,
  cd: () => number,
  ef: () => number
}

type FunctionPropertyKeyToNames<T> = {
  [K in keyof T]: T[K] extends Function ? K : never;
}

/* The only possible value for this  example will be { aa: never, ab: 'ab', cd: 'cd', ef: 'ef' } */
const example: FunctionPropertyKeyToNames<AB> = 

现在,使用 [keyof T] 我们只会得到值,
理论上never, 'ab', 'cd', 'ef',但由于 Typescript 不会never为你解析为值你
最终只会得到'ab', 'cd', 'ef'

于 2021-01-04T16:48:58.237 回答