首页 > 解决方案 > 为什么在使用类型映射时必须在“any”类型前面添加“keyof”

问题描述

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

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
};

它可以编译,所以这意味着 Type K可以分配给 typestring | number | symbol

那么为什么最初的错误说 Type K is not assignable to type string | number | symbol,为什么我添加了keyof它就可以了?

标签: typescript

解决方案


运算符in用于创建映射类型

它期望字符串、数字或符号的联合能够有效地迭代。如文档中所示:

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不是一个stringnumber或者symbol迭代,而是一个对象。由于我们要遍历键,因此可以使用keyof操作符来解决这个问题 return 'option1' | 'option2'

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

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

推荐阅读