文章目录

TypeScript类型系统中的any、unknown与never的适用场景

发布于 2026-05-18 15:14:29 · 浏览 26 次 · 评论 0 条

TypeScript类型系统中的any、unknown与never的适用场景

在TypeScript中,anyunknownnever是三个特殊且强大的基础类型。理解它们的区别和适用场景,是编写安全、健壮TypeScript代码的关键。本文将手把手教你如何正确选择和使用它们。


核心概念速览

在深入场景前,快速理解它们的本质:

  • any逃生舱。它会完全绕过TypeScript的类型检查。
  • unknown安全的标签。它表示“这里有一个值,但类型未知,你必须先检查才能使用它”。
  • never不可能存在的类型。它表示一个永远不会有值的类型,通常用于总抛出错误或进行穷尽检查的代码路径。

一、any类型:谨慎使用的“万能”逃生舱

any类型会关闭对其值的所有类型检查,它允许你进行任何操作而不会引发类型错误。

适用场景

  1. 处理动态或第三方内容
    当你引入一个没有类型定义文件(.d.ts)的第三方JavaScript库,或者需要处理来自非常动态的来源(如某些JSON.parse的结果或复杂DOM操作)的数据时,可以临时使用any。这是any最合理的用途之一。

    // 引入一个没有类型的旧库
    declare const LegacyChart: any;
    const chart = new LegacyChart();
    chart.draw(); // 不会报错
  2. 逐步迁移JavaScript项目到TypeScript
    在将大型JS代码库迁移到TS的初期阶段,你可能需要为许多变量临时标注any,以便先让编译器通过,后续再逐步添加具体类型。

  3. 编写极度灵活的通用函数(不推荐,但有时存在)
    在极少数情况下,你需要编写一个可以接受任何输入而无需关心其结构的函数。但请注意,这通常是设计上的缺陷。

风险与建议
过度使用any会使你的TypeScript代码失去大部分意义,等于回到了JavaScript时代。始终问自己:我是否真的无法知道这个值的类型?如果有可能,请优先考虑unknown或更具体的类型。


二、unknown类型:类型安全的守门员

unknownany的安全替代品。在赋值上,unknownany一样宽松——任何类型的值都可以赋给unknown类型的变量。但在使用这个值时,TypeScript会强制你进行类型检查或类型断言

适用场景

  1. 安全处理不确定的外部输入
    这是unknown最典型的使用场景。来自API响应、用户输入、JSON.parse或配置文件的数据,在验证其结构前,类型是未知的。

    async function fetchData(): Promise<unknown> {
      const response = await fetch('https://api.example.com/data');
      return response.json(); // 返回值类型是 `unknown`
    }
    
    // 使用数据前必须检查
    const data = await fetchData();
    
    // ❌ 直接使用会报错:‘data’ is of type ‘unknown’.
    // console.log(data.id);
    
    // ✅ 通过类型守卫进行安全检查
    if (typeof data === 'object' && data !== null && 'id' in data) {
      console.log((data as { id: number }).id); // 现在类型安全
    }
  2. 编写需要先检查后使用的通用函数
    当函数接收一个类型不确定的参数时,使用unknown可以强制函数体内部处理所有可能的类型情况。

    function processValue(value: unknown) {
      if (typeof value === 'string') {
        // 在这个块里,TypeScript知道 `value` 是 `string` 类型
        console.log(value.toUpperCase());
      } else if (typeof value === 'number') {
        // 在这个块里,`value` 是 `number` 类型
        console.log(value.toFixed(2));
      }
      // 如果不检查,这里无法对value做任何操作
    }
  3. 替代 any 作为函数的返回类型
    当函数可能返回多种类型的值,且无法用联合类型精确表达时,unknownany更安全。


三、never类型:逻辑上的“终点”

never类型表示那些永远不会有返回值的类型。这听起来奇怪,但在以下场景中非常有用。

适用场景

  1. 总是抛出错误的函数
    一个函数如果内部总是抛出异常,那么它永远不会正常执行完成并返回一个值。因此,其返回类型是never

    function throwError(message: string): never {
      throw new Error(message);
      // 后续代码是不可达的
    }
    
    // 常见的用于类型守卫中的断言函数
    function assertIsDefined<T>(value: T): asserts value is NonNullable<T> {
      if (value === null || value === undefined) {
        throwError('Value is not defined!');
      }
    }
  2. 穷尽检查(Exhaustive Checking)
    这是never最强大的应用之一,用于确保联合类型的每个成员都被处理了。当你对联合类型进行switchif-else判断时,如果能在默认分支中为变量赋值never类型,就能保证你处理了所有情况。如果未来新增了联合成员而未处理此处,TypeScript会报错。

    type Shape = 'circle' | 'square' | 'triangle';
    
    function getArea(shape: Shape): number {
      switch (shape) {
        case 'circle':
          return Math.PI * 1 * 1;
        case 'square':
          return 2 * 2;
        case 'triangle':
          return 0.5 * 2 * 3;
        default:
          // 将 `shape` 的类型收窄为 `never`
          const _exhaustiveCheck: never = shape;
          return _exhaustiveCheck; // 如果Shape类型新增成员而未处理此分支,此处会报类型错误
      }
    }
  3. 无法到达的代码路径
    在类型收窄后,如果某个分支在逻辑上不可能执行(例如,一个值已经通过判断被确认为string,那么后续检查它是否为number的代码块就是never类型)。


三者的对比与选择指南

类型 安全性 主要用途 代码示例
any 逃生舱:关闭类型检查,用于第三方库、迁移代码或极端灵活场景。 let x: any = 10; x.foo();
unknown 安全占位符:表示类型未知,使用前必须进行类型检查。用于外部输入、条件类型守卫。 let x: unknown = 10; if (typeof x === 'number') x.toFixed();
never - 逻辑终点:表示不可能存在的值。用于总抛错的函数、穷尽检查的default分支。 function fail(): never { throw new Error(); }

选择流程图

graph TD A[开始:面对一个不确定类型的变量] --> B{是否100%确定需要绕过类型检查?
(如:迁移旧代码)}; B -- 是 --> C[使用 `any`]; B -- 否 --> D[使用 `unknown` 作为安全起点]; D --> E{是否需要读取或操作该变量?}; E -- 是 --> F[**添加类型守卫**
(如:typeof, instanceof, 自定义守卫)]; F --> G[类型收窄后安全操作]; E -- 否 --> H[仅传递,不操作]; I[编写函数/逻辑分支] --> J{函数是否总会抛出错误或永不返回?}; J -- 是 --> K[返回类型使用 `never`]; J -- 否 --> L{是否在进行穷尽的switch/if-else检查?}; L -- 是 --> M[在 `default` 分支使用 `never` 进行断言]; L -- 否 --> N[根据实际返回类型选择];

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文