在使用typescript时,有时候我们需要知道一个对象的key值的类型
举个例子:有一个pack
对象,getValue
来根据传入key获取其值
const pack = {
reset: {
zh: '重置',
en: 'Reset',
},
search: {
zh: '查询',
en: 'Search',
},
};
const getValue = (key) => {
return pack[key];
};
此时ts报错参数“key”隐式具有“any”类型。ts(7006)
意思是传入函数的key值没有限制其类型
那写上key可能的值就好了
const getValue = (key: 'reset' | 'search') => {
return pack[key];
};
现在pack
只有两个key,以后增加了怎么办呢?所以不能手动添加
我们需要使用ts推断出pack
key的类型,key: keyof typeof pack
const getValue = (key: keyof typeof pack) => {
return pack[key];
};
typeof
typeof
是一个操作符,它用于获取一个变量、属性或表达式在运行时的类型。
上述示例中typeof pack
得到为
const pack: {
reset: {
zh: string;
en: string;
};
search: {
zh: string;
en: string;
};
};
keyof
keyof
是一个操作符,它返回一个对象类型的所有公共属性名的联合类型。
上述示例中keyof typeof pack
得到为
"search" | "reset"
到这里都比较好理解,但如果需要获取pack
第二级key值的类型
const getValue = (key: keyof typeof pack, locale) => {
return pack[key][locale];
};
增加了第二级key: locale
,此时也是报错参数“locale”隐式具有“any”类型。ts(7006)
locale
目测可以知道是'zh'|'en'
。那如何用推断的方式得到locale
的类型值呢?
extends
extends
关键字主要用于类继承,表示一个类继承自另一个类,还可以用于条件类型(Conditional Types),判断一个类是否属于另一个类
比如需要推断数组的元素类型
type Ids = number[];
type Names = string[];
// T extends Names? 可以解析为:如果泛型T属于string[]类型,则...
type Unpacked<T> = T extends Names ? string : T extends Ids ? number : never;
type idType = Unpacked<Ids>; // idType 类型为 number
type nameType = Unpacked<Names>; // nameType 类型为string
infer
infer
关键字通常与条件类型(Conditional Types)和映射类型(Mapped Types)一起使用,用于在类型推断过程中捕获类型信息。
同样是推断数组的元素类型,使用infer
:
// infer R 表示声明了一个类型R,用于捕获参数类型。如果传入T = string[],则 R = string
type Unpacked<T> = T extends (infer R)[] ? R : never;
type idType = Unpacked<Ids>; // idType 类型为 number
type nameType = Unpacked<Names>; // nameType 类型为string
回到pack
例子。我们先不使用keyof
,使用infer
来推断一下pack
的一级key类型
type GetKey<T> = T extends Record<infer R, any> ? R : never;
const getValue = (key: GetKey<typeof pack>) => {
return pack[key];
};
GetKey<typeof pack>
效果等同于 keyof typeof pack
那如何用infer
推断pack
的二级key类型?
type GetKey<T> = T extends Record<string, infer R>
? R extends Record<infer L, string>
? L
: never
: never;
// locale被推断为"zh" | "en"
const getValue = (key: keyof typeof pack, locale: GetKey<typeof pack>) => {
return pack[key][locale];
};
TypeScript中通过复杂的类型操作和转换,实现对类型的高级控制和计算,被称作为类型体操
关于keyof
、typeof
、extends
、infer
的更多用法请参阅其他资料