为什么在使用类型映射时必须在“ any”类型前面添加“ keyof”

时间:2019-09-26 04:40:56

标签: typescript

我想创建新的类型,而不是转换特定的类型,下面是我的代码:

type CustomMapped<K extends any , T> = {                         //can't compile
    [P in K]: T
};

它没有编译,错误是:

  

类型K不可分配给类型'string |编号符号”

所以我必须在{前面加上keyof

type CustomMapped<K extends keyof any , T> = ...                 //can compile

我很困惑,如果我将代码重写为:

type CustomMapped<K extends string | number | symbol, T> = {    //also compile
    [P in K]: T
};

它会编译,因此它表示类型K 可分配给类型string | number | symbol

那么为什么原来的错误说类型K是不能分配给类型string | number | symbol的原因,为什么我添加了keyof那么就可以了?

1 个答案:

答案 0 :(得分:2)

in运算符用于创建mapped types

它期望字符串,数字或符号的组合可以有效地进行迭代。如文档所示:

type Keys = 'option1' | 'option2';
type Flags = { [K in Keys]: boolean };

K将在第一个“迭代”上变为option1,在第二个“迭代”上变为option2。但是,如果Keys是对象,则将无法使用。

type Keys = { option1: any; option2: any };
type Flags = { [K in Keys]: boolean }; 
//                   ^^^^
// Type 'Keys' is not assignable to type 'string | number | symbol'.

因为Keys不是要迭代的stringnumbersymbol,而是对象。由于我们要遍历键,因此可以使用keyof运算符返回'option1' | 'option2'来解决。

以您的示例为例,您可以使用[P in keyof K]进行更新,它将评估为[P in 'option1' | 'option2']并按预期工作:

type CustomMapped<K extends any, T> = { [P in keyof K]: T };