TypeScript:undefined和null区别、应用场景

介绍

首先从语义和使用场景上区分两者:

特性 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

避免空值错误

  1. 使用可选链 ?.:访问属性/调用方法时,若左侧为 null/undefined,直接返回 undefined,避免报错:
    const obj: { a?: { b: number } } = {};
    console.log(obj.a?.b); // undefined(不会报错)
    
  2. 使用空值合并 ??:当左侧为 null/undefined 时,返回右侧值(比 || 更精准,|| 会过滤 0、’’ 等假值):
    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. 安全操作:优先用类型守卫、可选链 ?.、空值合并 ?? 处理空值,非空断言 ! 谨慎使用。