as const 类型断言
as const
是一种类型断言写法,好处就是可以在使用的时候 ts 可以推导出(infer)出真实的类型,而不需要加额外的判断。
举个例子,函数返回一个数组,这个数组会返回 shape 数据,如果是圆形则返回类型圆形+圆形的弧度
,如果是正方形则返回类型正方形+正方形的边长
。
const getShapes = () => {
const result = [
{ kind: 'circle', radius: 100 },
{ kind: 'square', sideLength: 50 },
];
return result;
};
for (const shape of getShapes()) {
if (shape.kind === 'circle') {
// Type 'number | undefined' is not assignable to type 'number'.
// Type 'undefined' is not assignable to type 'number'.ts(2322)
const radius: number = shape.radius;
} else {
// Type 'number | undefined' is not assignable to type 'number'.
// Type 'undefined' is not assignable to type 'number'.ts(2322)
const length: number = shape.sideLength;
}
}
如果没有加as const
就会出现上面注释中的 报错,因为返回的是一个普通的数组,它无法推断出元素的属性是否存在。
而如果加了之后,返回的数据类型就不是单纯的数组了,而是一个内容也被类型化
的数组。
const getShapes = () => {
const result = [
{ kind: 'circle', radius: 100 },
{ kind: 'square', sideLength: 50 },
] as const;
return result;
};
for (const shape of getShapes()) {
if (shape.kind === 'circle') {
// 无报错
const radius: number = shape.radius;
} else {
// 无报错
const length: number = shape.sideLength;
}
}
如果去掉变量的:number
约束,也可以不报错,但是在用的时候还是要判断是否为undefined
。
另外,加了as const
后,数据中的值是不可以修改的,因为还是那句话,它不是普通的对象了,而是根据实际值的类型
推导出来的类型。
比如:
const arr = [1, 2, 3];
arr.push(4);
const arrConst = [1, 2, 3] as const;
// Property 'push' does not exist on type 'readonly [1, 2, 3]'.ts(2339)
arrConst.push(4);
arrConst
的类型已经是readonly [1, 2, 3]
了,所以不能再 push 了。
注意
as const
断言是不能返回表达式进行断言的,必须是常量的值,比如:
// Error! A 'const' assertion can only be applied to a
// to a string, number, boolean, array, or object literal.
let a = (Math.random() < 0.5 ? 0 : 1) as const;
let b = (60 * 60 * 1000) as const;
// Works!
let c = Math.random() < 0.5 ? (0 as const) : (1 as const);
let d = 3_600_000 as const;