TypeScript 索引访问类型
索引访问类型
我们可以通过索引访问类型去查找另一个类型上的特定属性:
type A = {
name: string;
age: number;
sex: string;
}
type B = A['age']; //type B = number
因为索引名本身就是一个类型,所以我们也可以使用联合、keyof
和其他类型:
type A = {
name: string;
age: number;
sex: string;
}
type I1 = A['name' | 'age']; // type I1 = string | number
type I2 = A[keyof A]; // type I2 = string | number
type B = 'sex' | 'age';
type I3 = A[B]; // type I3 = string | number
如果你尝试查找一个不存在的属性,TypeScript会报错:
type A = {
name: string;
age: number;
sex: string;
}
type I1 = A['al']; // 报错: 类型“A”上不存在属性“al”。
接下来我们看另一个实例,我们使用number
获取数组元素的类型,结合typeof
可以方便的捕获数组字面量的元素类型:
const arr = [
{ name: '张三', age: 18 },
{ name: '李四', age: 28 },
{ name: '王五', age: 38 },
]
type A = typeof arr[number];
// type A = {
// name: string;
// age: number;
// }
type Age = typeof arr[number]['age']; // type Age = number
type Name = A['name']; //type Name = string
作为索引的只能是类型,这意味着你不能使用值或一个变量引用来作为索引名:
let key = 'age';
type Age = A[key]; //“key”表示值,但在此处用作类型。是否指“类型 key”?
最后讲一个案例: 假设我们有一个业务场景是这样的,一个页面可能在不同的APP使用,根据不同的APP调用的底层API会不一样,我们可能会这样写:
const APP = ['TaoBao', 'Tmall', 'Alipay'];
function getPhoto(app: string) {
// ...
}
getPhoto('TaoBao'); // ok
getPhoto('whatever'); // ok
如果我们对app
仅仅是约束为string
类型,那么传入其他字符串也不会报错。因此我们可以使用字面量联合类型来约束一下:
const APP = ['TaoBao', 'Tmall', 'Alipay'];
type App = 'TaoBao' | 'Tmall' | 'Alipay';
function getPhoto(app: App) {
// ...
}
getPhoto('TaoBao'); // ok
getPhoto('whatever'); // 报错:类型“"whatever"”的参数不能赋给类型“App”的参数
但是这样写代码太冗余了,我们可以结合typeof
操作符和索引访问类型来实现:
const APP = ['TaoBao', 'Tmall', 'Alipay'] as const;
type App = typeof APP[number];
// type App = "TaoBao" | "Tmall" | "Alipay"
function getPhoto(app: App) {
// ...
}
getPhoto('TaoBao'); // ok
getPhoto('whatever'); // 报错:类型“"whatever"”的参数不能赋给类型“App”的参数
我们来一步步解析:
首先是使用as const
将数组变为readonly
的元组类型:
const APP = ['TaoBao', 'Tmall', 'Alipay'] as const;
// const APP: readonly ["TaoBao", "Tmall", "Alipay"]
此时APP
还是值,我们通过typeof
获取APP
的类型:
type App = typeof APP; // type App = readonly ["TaoBao", "Tmall", "Alipay"]
最后再通过索引访问类型,获取到字符串联合类型:
type App = typeof APP[number];
// type App = "TaoBao" | "Tmall" | "Alipay"
需要注意的是,如果仅仅是使用索引访问类型来获取,而不将APP
转为元组的话,只会获得一个string
类型:
const APP = ['TaoBao', 'Tmall', 'Alipay'];
type App = typeof APP[number]; // type App = string