TypeScript 类型断言和类型注解的区别
1. 类型注解(Type Annotation)- useState<string | null>(null)
const [msg, setMsg] = useState<string | null>(null)
作用: 告诉 TypeScript 这个变量的类型应该是什么
特点:
- 声明类型:定义变量应该是什么类型
- 编译时检查:TypeScript 会检查赋值是否符合类型
- 类型推导:如果类型不匹配会报错
示例:
const [msg, setMsg] = useState<string | null>(null)
// msg 的类型是 string | null(只读)
// setMsg 的类型是 (value: string | null) => void
// ✅ 正确:使用 setter 函数
setMsg("hello") // ✅ 可以
setMsg(null) // ✅ 可以
setMsg(123) // ❌ 错误:不能传入 number
2. 类型断言(Type Assertion)- as HTMLInputElement
(input as HTMLInputElement).value = ''
作用: 告诉 TypeScript "相信我,这个值就是这个类型"
特点:
- 强制转换:不改变运行时值,只改变编译时的类型
- 绕过检查:告诉编译器"我知道我在做什么"
- 风险:如果类型不对,运行时可能出错
示例:
const input: HTMLElement | null = document.querySelector('input')
// input 的类型是 HTMLElement | null
// HTMLElement 没有 .value 属性
// 使用类型断言
(input as HTMLInputElement).value = '' // ✅ 编译通过
// 告诉 TypeScript:我知道 input 是 HTMLInputElement
对比表格
| 特性 | 类型注解 useState<string>
|
类型断言 as HTMLInputElement
|
|---|---|---|
| 时机 | 声明变量时 | 使用变量时 |
| 作用 | 定义类型 | 强制转换类型 |
| 检查 | 严格检查,类型不匹配会报错 | 绕过检查,相信开发者 |
| 风险 | 低(编译时检查) | 高(运行时可能出错) |
| 使用场景 | 定义新变量 | 已知类型但 TypeScript 不知道 |
实际例子
// 类型注解 - 定义类型
const [count, setCount] = useState<number>(0)
// count 的类型是 number,setCount 只能接收 number
// 类型断言 - 强制转换类型
const element = document.querySelector('.my-input')
// element 的类型是 Element | null
const input = element as HTMLInputElement
// 现在 input 的类型是 HTMLInputElement,可以访问 .value
总结
- 类型注解:定义类型,让 TypeScript 帮你检查
- 类型断言:强制转换,告诉 TypeScript "相信我"
最佳实践:
- 优先使用类型注解(更安全)
- 只在确实知道类型时才使用类型断言
- 避免过度使用类型断言(会失去类型检查的好处)