类型断言用于手动指定值的类型,告诉编译器"我知道这个值是什么类型"。
let value: unknown = "hello"
let length: number = (value as string).length
console.log(length) // 5
let value: unknown = "hello"
let length: number = (<string>value).length
console.log(length) // 5
注意:尖括号语法在 JSX 中与 React 语法冲突,推荐使用 as 语法。
let value: unknown = "hello world"
console.log((value as string).toUpperCase()) // "HELLO WORLD"
const input = document.getElementById("email") as HTMLInputElement
console.log(input.value)
let value: string | number = "hello"
let str: string = value as string
console.log(str.toUpperCase()) // "HELLO"
let value: any = "hello"
let num: number = value as number // 编译通过,运行时可能出错
console.log(num.toFixed(2)) // 运行时报错
极端情况下可以使用双重断言:
let value: string = "hello"
let num: number = value as unknown as number
console.log(num) // "hello"(字符串,不是数字)
双重断言很危险,尽量避免使用。
使用 as const 将类型锁定为字面量:
let name = "张三" as const
// 类型为 "张三",而不是 string
let arr = [1, 2, 3] as const
// 类型为 readonly [1, 2, 3]
let obj = { name: "张三", age: 25 } as const
// 类型为 { readonly name: "张三"; readonly age: 25 }
const config = {
endpoint: "/api",
timeout: 5000
} as const
// 类型为 { readonly endpoint: "/api"; readonly timeout: 5000 }
const points = [10, 20] as const
// 类型为 readonly [10, 20]
const [x, y] = points
使用 ! 断言值不为 null 或 undefined:
let value: string | null = "hello"
console.log(value!.toUpperCase()) // "HELLO"
const element = document.getElementById("app")!
element.innerHTML = "hello"
interface User {
id: number
name: string
}
async function fetchUser(id: number): Promise<User> {
const response = await fetch(`/api/users/${id}`)
const data = await response.json()
return data as User
}
document.addEventListener("click", (event) => {
const target = event.target as HTMLButtonElement
console.log(target.textContent)
})
function isString(value: unknown): value is string {
return typeof value === "string"
}
function process(value: unknown): void {
if (isString(value)) {
console.log(value.toUpperCase())
} else {
console.log((value as number).toFixed(2))
}
}
enum Status {
Active = "ACTIVE",
Inactive = "INACTIVE"
}
function getStatus(value: string): Status {
return value as Status
}
const status = getStatus("ACTIVE")
console.log(status === Status.Active) // true
let value: string = "hello"
let num: number = value as number // 编译通过
num.toFixed(2) // 运行时报错:num 实际是字符串
// 不推荐
let value = data as any
// 推荐
let value = data as { name: string; age: number }
// 不推荐:直接断言
function process(value: unknown) {
return (value as string).toUpperCase()
}
// 推荐:先检查类型
function process(value: unknown) {
if (typeof value === "string") {
return value.toUpperCase()
}
throw new Error("值不是字符串")
}
类型断言只影响编译时,不影响运行时:
let value: any = "hello"
let num: number = value as number
console.log(typeof num) // "string"
| 方式 | 安全性 | 说明 |
|---|---|---|
| 类型断言 | 低 | 编译器信任你的判断 |
| 类型守卫 | 高 | 运行时检查类型 |
// 类型断言
const element = document.getElementById("app") as HTMLDivElement
// 类型守卫
const element = document.getElementById("app")
if (element instanceof HTMLDivElement) {
// 安全使用
}