介绍
首先从语义和使用场景上区分两者:
| 特性 | undefined | null |
|---|---|---|
| 语义 | 表示「值未定义」「缺少值」(被动的) | 表示「空值」「有意清空的值」(主动的) |
| 默认值 | 未初始化的变量、未返回的函数默认返回 | 需手动赋值 |
undefined 应用场景
声明了变量但未赋值
let a: number;
console.log(a); // undefined(类型层面:a 的类型是 number | undefined)
函数参数未传递
function fn(x: number) {
console.log(x);
}
fn(); // 编译报错,但 JS 运行时 x 是 undefined
对象缺少属性
const obj = { name: "张三" };
console.log(obj.age); // undefined
null 的常见场景
主动表示「无值」(比如清空变量、表示空引用):
let user: string | null = "李四";
user = null; // 主动清空,语义明确
与后端交互时表示「空数据」(比如数据库字段为空):
interface User {
id: number;
avatar: string | null; // 头像可能为空(主动设置)
}
类型处理
TypeScript 对 undefined 和 null 的处理有几个关键规则,核心是 严格空检查(strictNullChecks)。
1. 严格空检查(核心配置)
在 tsconfig.json 中,strictNullChecks: true 是 TypeScript 严格模式的核心(strict: true 会自动开启此配置),开启后:
undefined和null是独立的类型,不能赋值给其他类型(除非显式声明)。- 关闭后(默认 false),
undefined/null可以赋值给任意类型(类似原生 JS),但不推荐。
示例(开启严格空检查):
// 正确:显式声明包含 undefined
let num1: number | undefined = undefined;
// 正确:显式声明包含 null
let num2: number | null = null;
// 错误:number 类型不能接收 undefined
let num3: number = undefined;
// 错误:string 类型不能接收 null
let str1: string = null;
2. 可选属性/参数与 undefined
- 可选属性:对象属性后加
?,等价于「属性类型 | undefined」interface Person { name: string; age?: number; // 等价于 age: number | undefined } const p1: Person = { name: "王五" }; // age 未传,默认 undefined - 可选参数:函数参数后加
?,等价于「参数类型 | undefined」function greet(name?: string) { // name 的类型是 string | undefined console.log(`Hello, ${name || "陌生人"}`); } greet(); // 输出:Hello, 陌生人
3. 非空断言操作符 !
如果你确定某个值一定不是 null/undefined,可以用 ! 告诉 TypeScript 编译器(注意:运行时如果是 null/undefined 会报错,需谨慎使用):
let str: string | null = "Hello";
// 非空断言:告诉编译器 str 一定不是 null/undefined
console.log(str!.length); // 输出:5
str = null;
// 运行时错误:Cannot read property 'length' of null
// console.log(str!.length);
4. 类型守卫:过滤 null/undefined
推荐用类型守卫(Type Guard)安全处理空值,避免运行时错误:
function getLength(str: string | null | undefined): number {
// 类型守卫:过滤 null/undefined
if (str == null) { // 等价于 str === null || str === undefined
return 0;
}
// 此时 str 的类型被收窄为 string
return str.length;
}
console.log(getLength("abc")); // 3
console.log(getLength(null)); // 0
console.log(getLength(undefined)); // 0
避免空值错误
- 使用可选链
?.:访问属性/调用方法时,若左侧为null/undefined,直接返回undefined,避免报错:const obj: { a?: { b: number } } = {}; console.log(obj.a?.b); // undefined(不会报错) - 使用空值合并
??:当左侧为null/undefined时,返回右侧值(比||更精准,||会过滤 0、’’ 等假值):let count: number | null = 0; console.log(count || 10); // 10(错误,0 被当成假值) console.log(count ?? 10); // 0(正确,仅 null/undefined 才返回 10)
总结
- 语义区别:
undefined表示「值未定义/缺失」(被动),null表示「空值」(主动)。 - 类型处理:开启
strictNullChecks后,undefined/null是独立类型,需显式声明(T | undefined/T | null)才能赋值。 - 安全操作:优先用类型守卫、可选链
?.、空值合并??处理空值,非空断言!谨慎使用。