TypeScript:undefined和null区别、应用场景 作者:马育民 • 2026-01-13 15:20 • 阅读:10001 # 介绍 首先从语义和使用场景上区分两者: | 特性 | undefined | null | |---------------------|--------------------------------------|-------------------------------------| | **语义** | 表示「值未定义」「缺少值」(被动的)| 表示「空值」「有意清空的值」(主动的) | | **默认值** | 未初始化的变量、未返回的函数默认返回 | 需手动赋值 | # undefined 应用场景 ### 声明了变量但未赋值 ```typescript let a: number; console.log(a); // undefined(类型层面:a 的类型是 number | undefined) ``` ### 函数参数未传递 ```typescript function fn(x: number) { console.log(x); } fn(); // 编译报错,但 JS 运行时 x 是 undefined ``` ### 对象缺少属性 ```typescript const obj = { name: "张三" }; console.log(obj.age); // undefined ``` # null 的常见场景 ### 主动表示「无值」(比如清空变量、表示空引用): ```typescript let user: string | null = "李四"; user = null; // 主动清空,语义明确 ``` ### 与后端交互时表示「空数据」(比如数据库字段为空): ```typescript 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),但不推荐。 **示例(开启严格空检查)**: ```typescript // 正确:显式声明包含 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」 ```typescript interface Person { name: string; age?: number; // 等价于 age: number | undefined } const p1: Person = { name: "王五" }; // age 未传,默认 undefined ``` - **可选参数**:函数参数后加 `?`,等价于「参数类型 | undefined」 ```typescript function greet(name?: string) { // name 的类型是 string | undefined console.log(`Hello, ${name || "陌生人"}`); } greet(); // 输出:Hello, 陌生人 ``` ### 3. 非空断言操作符 `!` 如果你确定某个值**一定不是** `null`/`undefined`,可以用 `!` 告诉 TypeScript 编译器(注意:运行时如果是 null/undefined 会报错,需谨慎使用): ```typescript 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)安全处理空值,避免运行时错误: ```typescript 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 ``` # 避免空值错误 1. **使用可选链 `?.`**:访问属性/调用方法时,若左侧为 `null`/`undefined`,直接返回 `undefined`,避免报错: ```typescript const obj: { a?: { b: number } } = {}; console.log(obj.a?.b); // undefined(不会报错) ``` 2. **使用空值合并 `??`**:当左侧为 `null`/`undefined` 时,返回右侧值(比 `||` 更精准,`||` 会过滤 0、'' 等假值): ```typescript let count: number | null = 0; console.log(count || 10); // 10(错误,0 被当成假值) console.log(count ?? 10); // 0(正确,仅 null/undefined 才返回 10) ``` # 总结 1. **语义区别**:`undefined` 表示「值未定义/缺失」(被动),`null` 表示「空值」(主动)。 2. **类型处理**:开启 `strictNullChecks` 后,`undefined`/`null` 是独立类型,需显式声明(`T | undefined`/`T | null`)才能赋值。 3. **安全操作**:优先用类型守卫、可选链 `?.`、空值合并 `??` 处理空值,非空断言 `!` 谨慎使用。 原文出处:http://www.malaoshi.top/show_1GW2aKUqW5aD.html