1. 基本含义
断言是开发者明确告诉编译器/运行时某个值的类型或状态的行为。
意思是:”我确定这个值是什么类型,请相信我”。
2. 在 TypeScript 中的三种断言 ★★★
2.1 类型断言(Type Assertion)
// 情况1:开发者比 TypeScript 更清楚值的类型
const value: any = "hello"
// 语法1:尖括号语法
const length1 = (<string>value).length // 告诉 TS:value 是 string
// 语法2:as 语法(更常用)
const length2 = (value as string).length // 告诉 TS:value 是 string
2.2 非空断言(Non-null Assertion)
// 告诉 TS:这个值一定不是 null/undefined
interface User {
name?: string
}
function greet(user: User) {
// ❌ 错误:可能为 undefined
// console.log(user.name.toUpperCase())
// ✅ 非空断言:我确定 name 有值
console.log(user.name!.toUpperCase())
// 等价于
if (user.name) {
console.log(user.name.toUpperCase())
}
}
2.3 确定赋值断言(Definite Assignment Assertion)
// 告诉 TS:这个变量会在构造函数之外初始化
class User {
name!: string // 我保证会在构造函数中赋值
constructor() {
this.initialize()
}
initialize() {
this.name = "John"
}
}
3. 在 Vue 3 模板中的断言
<template>
<!-- 模板中也可以使用类型断言 -->
<div v-if="user">
<!-- 这里 user 已经被类型收窄 -->
<span>{{ user.name }}</span>
</div>
<!-- 或者使用可选链 -->
<span>{{ user?.name }}</span>
</template>
<script setup>
import { ref } from 'vue'
const user = ref<{ name: string } | null>(null)
// 在 setup 中使用断言
const userName = computed(() => {
return user.value?.name || 'Guest'
})
// 或者在异步操作后
const loadUser = async () => {
const data = await fetchUser()
user.value = data as User // 类型断言
}
</script>
4. TypeScript 的断言函数
TypeScript 3.7+ 引入了断言函数:
// 自定义断言函数
function assertIsString(value: unknown): asserts value is string {
if (typeof value !== 'string') {
throw new Error('Not a string!')
}
}
// 使用
function example(value: unknown) {
assertIsString(value) // 如果执行到这里,value 一定是 string
console.log(value.toUpperCase()) // 安全
}
5. 总结
断言的核心思想:开发者在特定时刻比 TypeScript 编译器更清楚某个值的类型或状态。
| 概念 | 作用时机 | 示例 | 风险 |
|---|---|---|---|
| 类型断言 | 编译时 | value as string |
类型错误时运行时报错 |
| 非空断言 | 编译时 | value! |
值为空时运行时报错 |
| NonNullable | 编译时 | NonNullable<T> |
只是类型操作,无运行时风险 |
| 类型守卫 | 编译时+运行时 | typeof value === 'string' |
安全,有运行时检查 |
简单比喻:
- TypeScript 编译器:严格的老师
- 断言:学生对老师说:”老师,我确定这个答案是对的”
- 风险:如果学生错了,考试(运行时)会不及格(报错)
谨慎使用断言,尽量配合运行时验证,确保应用的稳定性。
