1. 断言了解
TypeScript 允许你覆盖它的推断,毕竟作为开发者你比编译器更了解你写的代码。
类型断言主要用于当 TypeScript 推断出来类型并不满足你的需求,你需要手动指定一个类型。
类型断言有两种方式:
- 使用"尖括号"语法
- 使用
as
语法
2. as
关键字
使用类型断言(as关键字)覆盖其类型推断:
let student = {}
// let student: {}
student.name = 'jack'
// 类型“{}”上不存在属性“name”。
student.age = 18
// 类型“{}”上不存在属性“age”。
TypeScript类型推断变量student
是一个没有属性的对象, 所以添加对象时会报错
此时就可以定义一个具有name
,age
属性的接口,然后通过as
关键字来进行类型断言
// 接口
interface Person{
name:string;
age: number
}
let student = {} as Person
// let student: Person
student.name = 'jack'
student.age = 18
此时student
的 类型使用断言类型, 而不是推断的类型, 因此添加name
,age
属性就不会报错
3. 断言的<>
语法
断言除了使用as关键字, 还在可以通过<>
语法来实现
interface Person{
name:string;
age: number
}
let student = {}
// let student: Person
student.name = 'jack'
student.age = 18
as
关键字使用在需要断言数据类型之后, 而<>
使用在断言数据之前
断言注意:
- 因为 类型断言是在编译时被删除,所以没有与类型断言关联的运行时检查
- 如果类型断言失败,则不会出现异常的生成(指的是TypeScript)
4. 非空断言运算符(后缀!)
TypeScript还具有一种特殊的语法, 用于在不进行任何显示检查的情况下从类型中删除null
,undefined
在任何表达式之后写!
,其实际上也是一种类型断言, 该值不是null
,或undefined
例如:
let num:number | null | undefined
// let num: number | null | undefined
let num2 = num.toFixed(2)
// 报错: Object is possibly 'null' or 'undefined'.
代码解释: 变量num
在获取toFixed
属性并调用时报错, 告知变量num
有可能是null
或undefined
而null
和undefined
类型的值是没有toFixed
属性.
此时我们就可以使用非空断言,
let num2 = num!.toFixed(2)
在变量num
后面添加非空断言符合!
, 来断言num
是非空值.
注意点:
和其他类型断言一样, 这种断言只会让TypeScript不报错, 但不会改变代码运行时的行为
简单说就是在编译后运行时如果num变量的值是null 或undefined ,JavaScript依然会报错
因此只有在你确定num
值不为null
,或undefined
时在使用它
5. 双重断言
双重断言极少有应用场景,只需要知道有这种操作即可:
例如:
interface Person{
name:string;
age: number;
hobby: string[]
}
// 断言不成功
let student:Person = 'jack' as Person
/*
报错:
类型 "string" 到类型 "Person" 的转换可能是错误的,
因为两种类型不能充分重叠。如果这是有意的,请先将表达式转换为
*/
示例中的断言不成功, TypeScript告诉我们string
类型转换为Person
有问题
此时就可以使用双重断言
interface Person{
name:string;
age: number;
hobby: string[]
}
// 断言不成功
let student:Person = 'jack' as unknown as Person
代码最后一行,使用as
关键字进行了两次断言, 先将string
类型断言为unknown
类型,在断言为Person
类型, 就不会有报错了
6. 小结:
- 慎用类型断言,除非你真的有把握。
- 类型断言是一个编译时语法,不涉及运行时。