TypeScript 教程 第9章:null 与 undefined 处理
📘 TypeScript 教程 第9章:null
与 undefined
处理
一、null
与 undefined
的基本概念
在 JavaScript 中,null
和 undefined
是两个特殊的值,表示“无”或“未定义”。
类型 | 含义 |
---|---|
undefined |
变量未赋值时的默认值,表示“尚未赋值” |
null |
表示“空值”,通常用于显式表示一个变量没有指向任何对象或值 |
let a: undefined = undefined;
let b: null = null;
二、--strictNullChecks
的作用(核心机制)
TypeScript 提供了编译选项 --strictNullChecks
,它是严格类型检查的一部分。
✅ 开启 --strictNullChecks
后的行为:
-
null
和undefined
不能赋值给其他类型; - 需要使用联合类型来处理可能为空的情况;
- 提高类型安全性,防止运行时错误。
let name: string = null; // ❌ 报错:Type 'null' is not assignable to type 'string'
✅ 正确写法(使用联合类型):
let name: string | null = null; // ✅ 合法
⚠️ 关闭 --strictNullChecks
的行为:
-
null
和undefined
可以赋值给任意类型; - 类型系统更宽松,但容易引发运行时错误。
三、联合类型处理空值(T | null
| undefined
)
联合类型是处理空值的标准方式。
✅ 常见用法:
function printName(name: string | null): void {
if (name === null) {
console.log("Name is missing");
} else {
console.log(`Hello, ${name}`);
}
}
🧠 更复杂的联合类型:
type Maybe<T> = T | null | undefined;
function processUser(user: Maybe<{ id: number; name: string }>): void {
if (user) {
console.log(`Processing user: ${user.name}`);
} else {
console.log("No user provided");
}
}
四、非空断言操作符(Non-null Assertion Operator)!
当你确定某个变量不可能为 null
或 undefined
时,可以使用非空断言操作符 !
来告诉 TypeScript 不需要进行空值检查。
✅ 示例:
let value: string | null = "hello";
console.log(value!.toUpperCase()); // ✅ 安全地调用方法
⚠️ 使用风险:
如果变量实际为 null
或 undefined
,会导致运行时错误。
let value: string | null = null;
console.log(value!.length); // ❗ 运行时报错:Cannot read property 'length' of null
五、可选属性与 undefined
接口中使用 ?
标记属性为可选,其类型自动包含 undefined
。
✅ 示例:
interface User {
id: number;
name: string;
email?: string; // 等价于 email: string | undefined
}
let user: User = {
id: 1,
name: "Alice"
};
六、安全访问嵌套对象属性(Optional Chaining)
使用 ?.
操作符可以安全访问嵌套对象属性。
✅ 示例:
interface Product {
id: number;
details?: {
name: string;
price: number;
};
}
let product: Product = { id: 1 };
console.log(product.details?.price); // 输出: undefined,不会报错
七、空值合并运算符(Nullish Coalescing)??
用于提供默认值,仅当左侧为 null
或 undefined
时才使用右侧值。
✅ 示例:
let input: string | null = null;
let result = input ?? "default"; // 输出: "default"
❗ 与 ||
的区别:
let input = "";
let result1 = input || "default"; // 输出: "default" (因为 "" 被视为 falsy)
let result2 = input ?? "default"; // 输出: "" (因为 input 不是 null/undefined)
八、类型守卫(Type Guards)与空值判断
✅ 使用条件判断:
function getLength(str: string | null): number {
if (str === null) {
return 0;
}
return str.length;
}
✅ 自定义类型守卫函数:
function isNotNull<T>(value: T | null | undefined): value is T {
return value !== null && value !== undefined;
}
let data: string | null = "hello";
if (isNotNull(data)) {
console.log(data.toUpperCase());
}
九、综合实战示例
// 定义一个泛型类型 ApiResponse<T>,用于表示 API 响应
type ApiResponse<T> = {
status: 'success' | 'error'; // 状态可以是 'success' 或 'error'
data?: T | null; // 可选的数据字段,类型为 T 或 null
message?: string; // 可选的错误消息字段
};
// 定义一个函数 fetchUserInfo,用于模拟获取用户信息的 API 请求
function fetchUserInfo(): ApiResponse<{ name: string }> {
// 模拟 API 请求失败
return {
status: 'error',
data: null,
message: 'User not found'
};
}
// 调用 fetchUserInfo 函数并获取响应
const response = fetchUserInfo();
// 根据响应状态处理结果
if (response.status === 'success' && response.data?.name) {
console.log(`User name: ${response.data.name}`);
} else {
console.error(response.message);
}
十、10道高频面试题(含详解)
Q1: --strictNullChecks
有什么作用?
✅ 答案:
开启后禁止将 null
和 undefined
赋值给其他类型,提高类型安全性。
Q2: 如何处理一个可能是 null
的变量?
✅ 答案:
使用联合类型 T | null
,并结合类型守卫或 !
断言。
Q3: !
操作符的作用是什么?有什么风险?
✅ 答案:
强制告诉 TS 该变量不为空,但如果实际为空会引发运行时错误。
Q4: null
和 undefined
的区别是什么?
✅ 答案:
-
null
表示“有意设置为空”; -
undefined
表示“未赋值”或“不存在”。
Q5: a ?? b
和 a || b
的区别?
✅ 答案:
-
??
仅在a == null
时返回b
; -
||
在a
为 falsy 值时就返回b
。
Q6: 如何定义一个可能为空的对象属性?
✅ 答案:
interface User {
id: number;
nickname?: string; // 等价于 string | undefined
}
Q7: 下面代码是否合法?
let value: string = null;
✅ 答案:
不合法(在 --strictNullChecks
开启的情况下),应改为:
let value: string | null = null;
Q8: 如何安全访问嵌套对象属性?
✅ 答案:
使用可选链 ?.
操作符:
obj?.prop?.nestedProp;
Q9: 如何编写一个类型守卫函数判断变量不为空?
✅ 答案:
function isDefined<T>(value: T | null | undefined): value is T {
return value !== null && value !== undefined;
}
Q10: null
是否可以赋值给 number
类型?
✅ 答案:
不可以(在 --strictNullChecks
开启下),必须使用联合类型 number | null
。
十一、总结
项目 | 内容 |
---|---|
核心机制 |
--strictNullChecks 、联合类型、非空断言 |
最佳实践 | 优先使用联合类型和类型守卫,谨慎使用 !
|
建议 | 打开 --strictNullChecks ,避免运行时错误 |
上一篇: 几秒钟就充满电!科学
下一篇: 暂无数据