TypeScript - 类型断言详解(as、!、?.、??、!!)
作者:hangge | 2026-08-06 09:38
在 TypeScript 开发过程中,有时编译器无法获取具体的类型信息,这时就需要使用类型断言(Type Assertion)来告诉编译器具体的类型。本文将详细介绍 TypeScript 中常用的类型断言语法,包括 as 关键字、非空断言 !、可选链 ?.、空值合并操作符 ?? 等内容。




一、基本介绍
1,什么是类型断言
类型断言(Type Assertion)是 TypeScript 中的一种机制,允许开发者手动指定一个值的类型。当 TypeScript 编译器无法自动推断出正确的类型时,我们可以通过类型断言来明确告诉编译器具体的类型信息。
2,常用的类型断言方式
- as 语法:使用 as 关键字进行类型断言
- 非空断言 !:断言某个值不为 null 或 undefined
- 可选链 ?.:安全访问对象属性,避免空值错误
- 空值合并 ??:当值为 null 或 undefined 时提供默认值
- 双重否定 !!:将任意值转换为布尔类型
二、类型断言 as
1,基本语法
(1)在 TypeScript 中,可以使用 as 关键字进行类型断言,语法格式为:值 as 类型。
(2)举个例子,通过 document.getElementById 获取 <img> 元素时,TypeScript 只知道该函数会返回 HTMLElement,并不知道它具体的类型:
// 类型断言 as(案例1)
const myEl = document.getElementById("my-img");
// 报错:Property 'src' does not exist on type 'HTMLElement'
myEl.src = "图片地址";
(3)这时可以使用 as 关键字进行类型断言:
提示:HTMLImageElement 是 HTMLElement 的子类型,包含了 src、alt 等图片特有的属性。
// 使用 as 关键字断言为 HTMLImageElement
const myEl = document.getElementById("my-img") as HTMLImageElement;
// 不会报错,因为明确断定 myEl 是 HTMLImageElement
myEl.src = "图片地址";
2,类型断言案例:类继承
(1)在下面的案例中,sayHello 函数接收一个 Person 类型的参数,但我们想调用 Student 类特有的方法:
// 类型断言 as(案例2)
class Person {}
class Student extends Person {
studying() {
console.log("正在学习");
}
}
function sayHello(p: Person) {
// 报错:Property 'studying' does not exist on type 'Person'
p.studying();
}
const stu = new Student();
sayHello(stu);
(2)可以使用 as 关键字对 p 进行类型断言:
function sayHello(p: Person) {
// 使用类型断言 as,将 p 断言为 Student
(p as Student).studying(); // 可以调用 studying 方法
}
const stu = new Student();
sayHello(stu); // 输出: 正在学习

3,类型断言的限制
(1)TypeScript 只允许将类型断言转换为更具体或者不太具体的类型版本,此规则可以防止不合理的强制转换:
// 不合理的类型强制转换会报错 const message = "Hello World"; // 错误:Conversion of type 'string' to type 'number' may be a mistake. const num: number = message as number;
(2)如果确实需要进行类型转换,可以将类型先转换为 any 或 unknown 类型:
注意:虽然可以通过 any 或 unknown 绕过类型检查,但这会失去类型安全保护,可能导致运行时错误,应谨慎使用。
const message = "Hello World"; // 报错:Type 'string' is not assignable to type 'number' // const num1: number = message; // 方式一:先断言为 unknown,再断言为 number const num2: number = (message as unknown) as number; // 方式二:先断言为 any,再断言为 number const num3: number = (message as any) as number; console.log(num2, num3); // 输出: Hello World Hello World
三、非空类型断言 !
1,基本语法
(1)在 JavaScript 中,经常使用 if 语句进行非空判断。而在 TypeScript 中,除了 if 语句,还可以使用非空类型断言(Non-null Assertion)进行非空判断。
(2)非空类型断言使用 ! 操作符,表示可以确定某个标识符一定是有值的,可以跳过 TypeScript 在编译阶段对它的检测。
2,使用场景
(1)下面是一个可选参数的案例,message 参数是可选的,值可能为 undefined 或 string。下面代码在执行 TypeScript 编译时会报错,因为传入的 message 可能为 undefined,这时就无法访问 length 属性。
// 参数 message 是可选的,值可能为 undefined 或 string
function printMessageLength(message?: string) {
// 编译报错:Object is possibly 'undefined'
console.log(message.length);
}
printMessageLength("coder");
(3)有两种解决方式。第一种是使用 if 语句进行非空判断:
function printMessageLength(message?: string) {
// 方式一:使用 if 进行非空判断
if (message) {
console.log(message.length);
}
}
printMessageLength("coder"); // 输出: 5

(4)第二种是使用非空类型断言 !:
注意:使用非空断言 ! 时,如果值确实为 null 或 undefined,运行时会报错。因为它只是跳过了编译阶段的类型检查,并没有真正进行非空判断。建议在确定值一定不为空的情况下使用。
function printMessageLength(message?: string) {
// 方式二:使用非空类型断言 !
// 这里断言 message 一定有值,跳过 TypeScript 编译阶段的检测
console.log(message!.length);
}
printMessageLength("coder"); // 输出: 5
四、可选链操作符 ?.
1,基本概念
(1)可选链(Optional Chaining)是 ES11(ES2020)中新增的特性,使用可选链操作符 ?. 来安全访问对象属性。
(2)可选链的作用:
- 当对象的属性不存在时,会发生短路,直接返回 undefined
- 当对象的属性存在时,才会继续执行
- 避免因中间值为 null 或 undefined 而抛出错误
提示:虽然可选链是 ECMAScript 提出的特性,但在 TypeScript 中的使用效果更佳,可以结合类型系统实现更安全的属性访问。
2,使用示例
(1)首先定义一个复杂的对象类型和实例:
// 为对象类型起一个 Person 别名
type Person = {
name: string;
friend?: {
name: string;
age?: number;
girlFriend?: {
name: string;
};
};
};
// 定义一个对象,指定类型为 Person 类型
const info: Person = {
name: "hangge",
friend: {
name: "kobe",
girlFriend: {
name: "lily"
}
}
};
(2)使用可选链访问对象的属性:
提示:可选链 ?. 与非空断言 ! 的区别:可选链在值不存在时会返回 undefined 而不报错,而非空断言在值不存在时会导致运行时错误。
// 获取 info 对象的属性,使用可选链 ?. console.log(info.name); // 输出: hangge // 使用非空断言 !:当 friend 为空时,运行程序会报错 // console.log(info.friend!.name); // 使用可选链 ?.:当 friend 不为空时,才取 age console.log(info.friend?.age); // 输出: undefined // 多层可选链:当 friend、girlFriend 都不为空时,才取 name console.log(info.friend?.girlFriend?.name); // 输出: lily
五、!! 双重否定操作符
1,基本用法
(1)!! 操作符可以将一个其他类型的值转换成 boolean 类型,类似于 Boolean(变量) 这种函数转换的方式。
- 简单来说:第一个 ! 将值转换为布尔值并取反,第二个 ! 再次取反,最终得到原值对应的布尔值。
const message = "Hello World"; // 方式一:以前转换 boolean 类型的方式 const flag1 = Boolean(message); console.log(flag1); // 输出: true // 方式二:使用 !! 操作符转成 boolean 类型 const flag2 = !!message; console.log(flag2); // 输出: true

(2)!! 操作符的转换规则:
- 假值(false、0、""、null、undefined、NaN)转换为 false
- 其他所有值转换为 true
// !! 操作符转换示例
console.log(!!0); // false
console.log(!!""); // false
console.log(!!null); // false
console.log(!!undefined); // false
console.log(!!1); // true
console.log(!!"hello"); // true
console.log(!!{}); // true
console.log(!![]); // true
六、?? 空值合并操作符
1,基本概念
(1)?? 操作符是 ES11 新增的空值合并操作符(Nullish Coalescing Operator),用于判断一个值是否为 null 或 undefined。
(2)具体来说,当左侧操作数为 null 或 undefined 时,返回右侧操作数;否则返回左侧操作数。
2,与 || 操作符的区别
(1)?? 与 || 的关键区别在于判断逻辑不同:
- || 操作符:判断左侧是否为假值(包括 false、0、""、null、undefined、NaN)
- ?? 操作符:只判断左侧是否为 null 或 undefined
(2)下面通过代码对比三种判空方式:
let message: string | null = 'Hello World'; // 方式一:使用三元运算符判空,赋默认值 // 会判断 null、undefined、''、false 为假 const content1 = message ? message : "你好啊,小刘1"; // 方式二:使用 || 操作符判空,赋默认值 // 会判断 null、undefined、''、false 为假 const content2 = message || "你好啊,小刘2"; // 方式三:使用 ?? 操作符判空,赋默认值 // 只判断 null 或 undefined 为假 const content3 = message ?? "你好啊,小刘3"; console.log(content1, content2, content3); // 输出: Hello World Hello World Hello World

(3)当值为空字符串或 0 时的区别:
提示:在需要保留 0 或空字符串 "" 作为有效值的场景下,应该使用 ?? 而不是 ||。
// 当值为空字符串时 let str: string = ""; console.log(str || "默认值"); // 输出: 默认值(空字符串被视为假值) console.log(str ?? "默认值"); // 输出: ''(空字符串不是 null 或 undefined) // 当值为 0 时 let num: number = 0; console.log(num || 100); // 输出: 100(0 被视为假值) console.log(num ?? 100); // 输出: 0(0 不是 null 或 undefined)
全部评论(0)