类型断言
类型断言(Type Assertion)可以用来手动指定一个值的类型。
案例
比如说我们有一个案例:定义一个函数,获取到一个数组或者字符串的长度
OK,接下来编写代码:
javascript
// 定义一个函数,获取到一个数组或者字符串的长度
function getLength(x: string | number): number {
return x.length
}
这样子就是先了这个功能,但是会有一个问题,就是,.length
方法是字符串特有的,对于数字来说,没有这个方法,因此在传入数字的时候,会报错,所以 ts 不允许这样写,会报错。
也就是说,如果使用联合声明的话,里面的结构体只能使用两个声明类型的共有方法,字符串和数字共有的一个方法是 .toString()
方法转为字符串,所以说我们可以使用一下:
javascript
// 定义一个函数,获取到一个数组或者字符串的长度
function getLength(x: string | number): number {
return x.toString().length
}
这样就是可以的了,不会引发 ts 校验错误问题:
所以我们可以测试一下子,编译完成执行一下操作,是不会有问题的。
javascript
// 定义一个函数,获取到一个数组或者字符串的长度
function getLength(x: string | number): number {
return x.toString().length
}
console.log(getLength("123456"));
console.log(getLength(123456));
看一下结果:
没有任何问题!
还有一个解决办法,就是我们先判断传进来的数据有没有 .length
方法,如果有就返回 .length
,如果没有在调用 .toString()
方法再返回。
javascript
function getLength(x: string | number): number {
if (x.length) {
return x.length
} else {
return x.toString().length
}
}
但是我们发现,其实也是不行的,和上面的问题一样,就是 .length 的时候,他不敢保证你穿进来的参数就是有的,所以语法校验直接不通过。
这个时候我们就需要使用今天要说的 类型断言,手动指定一个类型。
类型断言
类型断言有两种方法:
- 变量 as 类型
- <类型>变量
注意:在 tsx 语法(React 的 jsx 语法的 ts 版)中必须使用前者,即 值 as 类型。
我们用变量 as 类型
这个方法修改一下上面案例代码,指定一下内容:
看,我们在第一个地方指定了之后,已经不会报错了,但是后面没有指定的地方依旧在报错。
好,下面我们使用<类型>变量
的方式断言后面的内容:
这样我们就使用断言,指定了参数的类型。
将任何一个类型断言为 any 类型
现在,我们想在 window
上面添加一个 a
属性赋值为10
。
javascript
window.a = 10
理论上这样写是没有问题的,但是我们看 ts 的处理结果。
他给我们报错了。他说 window
上面没有 a
属性,确实哈,确实没有,但是老子写的代码老子不晓得嘛!老子今天就是想给 window
上添加一个 a
属性的!凭啥不让老子添加!
不让添加没办法,我们就给 window 断言成 any 类型:
javascript
(window as any).a = 10
好的,不报错了:
因为 any
类型是允许我们访问任何属性和方法的!所以有没有这个属性,有没有这个方法它不晓得,都让添加和操作,当然这是 any
类型的优点,相当灵活,确实也是他的一个缺点,太灵活,没有制约了。
注意一点:将一个变量断言为 any
可以说是解决 TypeScript 中类型问题的最后一个手段
。它极有可能掩盖了真正的类型错误
,所以如果不是非常确定,就不要使用 as any
。
总之,一方面不能滥用 as any
,另一方面也不要完全否定它的作用,我们需要在类型的严格性和开发的便利性之间掌握平衡(这也是 TypeScript 的设计理念之一),才能发挥出 TypeScript 最大的价值。
有一句话说得好:如果老是用 any
的话,我还用 ts
干什么!直接 js
走起啊! 啊哈哈哈哈,很有道理!
将 any 断言为一个具体类型
比如下面我有一段代码,存在一个函数,函数的目的是两参数相加,返回相加结果,但是传入的参数包括返回值都是 any 类型:
javascript
function abc(x:any, y:any):any {
return x + y
}
let a = abc(1, 2)
你看哈,我们调用方法传进去的参数都是数值类型,那我们想返回的数据也就是得到的 a
也是数值类型,那么我们可以添加断言,规定返回我数值类型的返回值,也就是返回我确定的类型:
javascript
function abc(x:any, y:any):any {
return x + y
}
let a = abc(1, 2) as number
这时候把鼠标一上去,发现 a
的类型变成 number
类型了。
如果想得到字符串,我们可以断言成字符串类型,毕竟我们已经确认我们传进去的是啥类型里:
javascript
function abc(x:any, y:any):any {
return x + y
}
let a = abc(1, 2) as number
let b = abc("1", "2") as string
OK,就是这个样子。