You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript中void、never、null、undefined的区别及适用场景

TypeScript中null、undefined、unknown、never四种类型的区别与实际示例

以下讨论完全聚焦TypeScript编译时类型,而非JavaScript运行时的值,核心讲TS类型系统里这四个特殊类型的语义差异和实际用法。


1. null类型

语义

专门标记主动赋值为空的对象值——意思是这个变量本应该指向一个对象,但我们明确让它暂时没有指向任何对象。

实际场景示例

// 声明一个明确为null的变量,比如未加载的用户头像
let userAvatar: null = null;

// 从缓存取数据,找不到就返回null
function getCachedUser(id: string): User | null {
  return userCache.has(id) ? userCache.get(id) : null;
}

const currentUser = getCachedUser("123");
// 必须先检查null,TS才会允许访问对象属性
if (currentUser !== null) {
  console.log(currentUser.nickname); // 编译时完全安全
}

2. undefined类型

语义

标记未初始化的变量或者函数中未传递的可选参数——强调"这个值还没被赋值",不是主动设为空。

实际场景示例

// 声明一个未初始化的变量,类型为undefined
let tempConfig: undefined;

// 函数的可选参数,没传的时候自动是undefined类型
function sendMessage(content: string, recipient?: string) {
  // recipient的类型是string | undefined
  const target = recipient || "全体成员";
  console.log(`发送给${target}: ${content}`);
}

sendMessage("开会通知"); // 正常执行,recipient为undefined

3. unknown类型

语义

表示类型完全未知的值,是TypeScript里最安全的"任意类型"——和any最大的区别是,它不会绕过类型检查,你必须先明确它的类型才能操作。

实际场景示例

// 接口返回的数据类型不确定,用unknown接收
async function fetchApiData(url: string): Promise<unknown> {
  const response = await fetch(url);
  return response.json();
}

async function renderUserInfo() {
  const rawData = await fetchApiData("/api/user");
  
  // 直接访问rawData.name会报错:TS不知道它是什么类型
  // console.log(rawData.name);

  // 必须先做类型收窄
  if (typeof rawData === "object" && rawData !== null && "name" in rawData) {
    console.log(`用户名:${rawData.name}`); // 编译时安全
  }
}

4. never类型

语义

表示永远不会发生的情况——比如函数永远不会返回(要么抛错,要么无限循环),或者穷尽枚举所有可能性后的兜底分支。它是TS类型系统的"底部类型",没有任何值能赋值给它。

实际场景示例

// 抛错的函数,永远不会返回,类型为never
function throwFatalError(msg: string): never {
  throw new Error(`致命错误:${msg}`);
}

// 无限循环的函数,永远不会返回
function keepRunning(): never {
  while (true) {
    console.log("程序持续运行中...");
  }
}

// 穷尽检查枚举,确保没有遗漏分支
enum OrderStatus {
  Pending,
  Paid,
  Shipped,
  Cancelled
}

function handleOrder(status: OrderStatus) {
  switch (status) {
    case OrderStatus.Pending:
      console.log("订单待支付");
      break;
    case OrderStatus.Paid:
      console.log("订单已支付");
      break;
    case OrderStatus.Shipped:
      console.log("订单已发货");
      break;
    case OrderStatus.Cancelled:
      console.log("订单已取消");
      break;
    // 如果新增了枚举值,TS会直接编译报错,因为status无法赋值给never
    default:
      const _ensureAllCasesHandled: never = status;
      throwFatalError(`未知订单状态:${_ensureAllCasesHandled}`);
  }
}

核心区别速览

类型核心语义编译时特点
null主动设为空的对象值需显式检查后才能访问对象属性
undefined未赋值/未传递的值常用于可选参数、未初始化变量
unknown类型未知的值必须类型收窄后操作,安全替代any
never永远不会发生的情况无值可赋值,用于穷尽检查、永不返回的函数

内容的提问来源于stack exchange,提问作者Gerard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 15:50:36