# 类型断言

发布时间 2023-12-26 10:56:39作者: 我是ed

类型断言

参考资料:https://ts.xcatliu.com/basics/type-assertion.html

类型断言(Type Assertion)可以用来手动指定一个值的类型。

案例

比如说我们有一个案例:定义一个函数,获取到一个数组或者字符串的长度

OK,接下来编写代码:

// 定义一个函数,获取到一个数组或者字符串的长度
function getLength(x: string | number): number {
  return x.length
}

这样子就是先了这个功能,但是会有一个问题,就是,.length 方法是字符串特有的,对于数字来说,没有这个方法,因此在传入数字的时候,会报错,所以 ts 不允许这样写,会报错。

在这里插入图片描述

也就是说,如果使用联合声明的话,里面的结构体只能使用两个声明类型的共有方法,字符串和数字共有的一个方法是 .toString() 方法转为字符串,所以说我们可以使用一下:

// 定义一个函数,获取到一个数组或者字符串的长度
function getLength(x: string | number): number {
  return x.toString().length
}

这样就是可以的了,不会引发 ts 校验错误问题:

在这里插入图片描述
所以我们可以测试一下子,编译完成执行一下操作,是不会有问题的。

// 定义一个函数,获取到一个数组或者字符串的长度

function getLength(x: string | number): number {
  return x.toString().length
}
console.log(getLength("123456"));
console.log(getLength(123456));

看一下结果:

在这里插入图片描述

没有任何问题!

还有一个解决办法,就是我们先判断传进来的数据有没有 .length 方法,如果有就返回 .length,如果没有在调用 .toString() 方法再返回。

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

window.a = 10

理论上这样写是没有问题的,但是我们看 ts 的处理结果。

在这里插入图片描述

他给我们报错了。他说 window 上面没有 a 属性,确实哈,确实没有,但是老子写的代码老子不晓得嘛!老子今天就是想给 window 上添加一个 a 属性的!凭啥不让老子添加!

不让添加没办法,我们就给 window 断言成 any 类型:

(window as any).a = 10

好的,不报错了:

在这里插入图片描述

因为 any 类型是允许我们访问任何属性和方法的!所以有没有这个属性,有没有这个方法它不晓得,都让添加和操作,当然这是 any 类型的优点,相当灵活,确实也是他的一个缺点,太灵活,没有制约了。

注意一点:将一个变量断言为 any 可以说是解决 TypeScript 中类型问题的最后一个手段。它极有可能掩盖了真正的类型错误,所以如果不是非常确定,就不要使用 as any

总之,一方面不能滥用 as any,另一方面也不要完全否定它的作用,我们需要在类型的严格性和开发的便利性之间掌握平衡(这也是 TypeScript 的设计理念之一),才能发挥出 TypeScript 最大的价值。

有一句话说得好:如果老是用 any 的话,我还用 ts 干什么!直接 js 走起啊! 啊哈哈哈哈,很有道理!

将 any 断言为一个具体类型

比如下面我有一段代码,存在一个函数,函数的目的是两参数相加,返回相加结果,但是传入的参数包括返回值都是 any 类型:

function abc(x:any, y:any):any {
  return x + y
}
let a = abc(1, 2)

你看哈,我们调用方法传进去的参数都是数值类型,那我们想返回的数据也就是得到的 a 也是数值类型,那么我们可以添加断言,规定返回我数值类型的返回值,也就是返回我确定的类型:

function abc(x:any, y:any):any {
  return x + y
}
let a = abc(1, 2) as number

这时候把鼠标一上去,发现 a 的类型变成 number 类型了。

在这里插入图片描述

如果想得到字符串,我们可以断言成字符串类型,毕竟我们已经确认我们传进去的是啥类型里:

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,就是这个样子。