🚀 如何使用TypeScript的null和undefined类型
欢迎来到我的博客文章!所有文章都是满满的前端干货,文章简明扼要。
基本概念
null 和 undefined 是 TypeScript 中的两个特殊类型,分别对应 JavaScript 中的两个原始值。
let u: undefined = undefined;
let n: null = null;
let num: number = undefined;
let str: string = null;
strictNullChecks 配置
TypeScript 的行为取决于 tsconfig.json 中的 strictNullChecks 配置。
❌ 关闭时(默认旧版本行为)
{
"compilerOptions": {
"strictNullChecks": false
}
}
let name: string = null;
let age: number = undefined;
function greet(name: string) {
console.log(name.toUpperCase());
}
greet(null);
✅ 开启时(推荐)
{
"compilerOptions": {
"strictNullChecks": true,
"strict": true
}
}
let name: string = null;
let age: number = undefined;
let nullableName: string | null = null;
let optionalAge: number | undefined = undefined;
null vs undefined 的区别
| 特性 | null | undefined |
| 含义 | 明确表示"空值" | 表示"未定义"或"缺失" |
| typeof | "object"(历史遗留bug) | "undefined" |
| 使用场景 | 主动赋值为空 | 变量未初始化、函数无返回值 |
| JSON.stringify | 保留为 null | 被忽略或转为 null |
| 数值转换 | 转为 0 | 转为 NaN |
非空断言操作符(Non-null Assertion)
1. ! 操作符
let name: string | null = "Alice";
console.log(name!.length);
let maybeNull: string | null = null;
console.log(maybeNull!.length);
⚠️ 警告
非空断言会绕过 TypeScript 的类型检查,使用时要确保值确实不为 null/undefined,否则会导致运行时错误。
可选链操作符(Optional Chaining)
interface User {
name: string;
address?: {
city: string;
street?: string;
};
}
const user: User = { name: "Alice" };
const city1 = user && user.address && user.address.city;
const city2 = user?.address?.city;
const street = user?.address?.street;
空值合并操作符(Nullish Coalescing)
TypeScript 3.7+ 支持 ?? 操作符,用于处理 null 和 undefined。
const inputValue = null;
const defaultValue = "default";
const result1 = inputValue ?? defaultValue;
const result2 = inputValue || defaultValue;
?? vs || 的区别
const count = 0;
const countWithOr = count || 10;
const countWithNullish = count ?? 10;
const emptyString = "";
const strWithOr = emptyString || "default";
const strWithNullish = emptyString ?? "default";
实战示例
示例 1:配置对象
interface Config {
timeout?: number;
retries?: number;
}
function createConnection(config: Config) {
const timeout = config.timeout ?? 5000;
const retries = config.retries ?? 3;
console.log(`Timeout: ${timeout$}, Retries: ${retries$}`);
}
createConnection({});
createConnection({ timeout: 0 });
示例 2:API 响应处理
interface ApiResponse {
data?: {
user?: {
name: string;
email?: string;
};
};
}
function getUserEmail(response: ApiResponse): string {
return response?.data?.user?.email ?? "No email provided";
}
const response1: ApiResponse = {};
console.log(getUserEmail(response1));
const response2: ApiResponse = {
data: { user: { name: "Alice", email: "alice@example.com" } }
};
console.log(getUserEmail(response2));
示例 3:类型守卫
function processValue(value: string | null | undefined) {
if (value === null || value === undefined) {
console.log("Value is null or undefined");
return;
}
console.log(value.toUpperCase());
const safeValue = value ?? "default";
console.log(safeValue.toUpperCase());
}
最佳实践
✅ 推荐做法
- 始终开启 strictNullChecks:在 tsconfig.json 中设置
"strict": true - 使用可选链和空值合并:简化 null/undefined 检查
- 明确区分 null 和 undefined:null 表示"空值",undefined 表示"未定义"
- 避免过度使用非空断言:! 操作符会绕过类型检查
- 使用联合类型:
string | null 明确表示可能为空
推荐模式
const city = user && user.address && user.address.city;
const city = user?.address?.city ?? "Unknown";
const count = config.count || 10;
const count = config.count ?? 10;
常见陷阱
陷阱 1:typeof null === "object"
if (typeof value === "object") {
}
if (typeof value === "object" && value !== null) {
}
陷阱 2:JSON.stringify 的行为
const obj = {
a: null,
b: undefined,
c: "value"
};
JSON.stringify(obj);
核心要点总结
💡 关键知识点
- strictNullChecks:开启后 null 和 undefined 不再是所有类型的子类型
- 可选链 ?.:安全访问可能为 null/undefined 的属性
- 空值合并 ??:只处理 null/undefined,不处理其他 falsy 值
- 非空断言 !:告诉编译器值不为 null,但要谨慎使用
- 类型守卫:通过显式检查收窄类型