TypeScript中any、unknown、never的区别

198 阅读3分钟

在 TypeScript 中,anyunknownnever 是三种特殊的类型,它们有各自的使用场景和区别:


1. any(任意类型,不安全)

  • any 表示 任何类型,它绕过了 TypeScript 的类型检查。
  • 适用于不确定类型的数据,但会丧失类型安全性
  • 可以对 any 类型的变量执行任何操作,不会有编译错误。

示例

ts
复制编辑
let value: any;

value = 123;
value = "hello";
value = true;

// 可以调用任意方法,不会有类型错误
value.toUpperCase();  // OK
value();              // OK(即使它不是一个函数)
value.age;            // OK(即使它没有这个属性)

any 的问题

  • 绕过了类型检查,导致代码变得不安全。
  • 一旦一个值是 any,它会污染整个代码,导致类型检查失效。

2. unknown(未知类型,更安全)

  • unknown 也是任意值的容器,但它比 any 更安全。
  • 不能直接对 unknown 类型的变量执行操作,必须先进行类型检查
  • 适用于不确定类型的变量,但仍想保留类型检查。

示例

ts
复制编辑
let value: unknown;

value = 123;
value = "hello";

// 不能直接调用方法(需要类型检查)
value.toUpperCase();  // 报错

// 需要先进行类型检查
if (typeof value === "string") {
  console.log(value.toUpperCase());
}

unknown 的优点

  • any 更安全,因为必须进行类型检查才能操作它。

  • 适用于外部 API 返回值不确定的情况,例如:

    ts
    复制编辑
    function getData(): unknown {
      return fetch("https://api.example.com/data").then(res => res.json());
    }
    

3. never(不可能的类型)

  • never 表示 永远不会发生的情况,即一个函数永远不会返回

  • 适用于:

    1. 抛出错误的函数。
    2. 死循环的函数。
    3. 严格的类型检查(不应该到达的代码)。

示例

ts
复制编辑
// 1. 抛出错误的函数
function throwError(message: string): never {
  throw new Error(message);
}

// 2. 死循环的函数
function infiniteLoop(): never {
  while (true) {}
}

// 3. 严格的类型检查
function checkType(value: string | number) {
  if (typeof value === "string") {
    console.log("String:", value);
  } else if (typeof value === "number") {
    console.log("Number:", value);
  } else {
    // 这里的 `never` 表示 value 不可能是其他类型
    const unreachable: never = value;
  }
}

never 的作用

  • 确保代码的完整性,不应该有额外的分支
  • TypeScript 可以帮助检查逻辑错误(如 switch 语句的遗漏分支)。

4. any vs unknown vs never 对比

类型作用是否可以赋值给其他类型是否可以执行操作安全性
any任意类型可以赋值给任何类型可以直接操作(但不安全)不安全
unknown不确定类型可以赋值给 anyunknown不能直接操作,必须先判断类型更安全
never不可能的类型不能赋值给任何类型(除了 never 本身)不能直接使用最高安全性

5. 什么时候使用?

  • any尽量避免使用,除非你真的不关心类型,比如迁移 JavaScript 代码时。
  • unknown推荐用于不确定类型的变量,例如 API 返回的数据,然后进行类型检查。
  • never:用于确保代码逻辑的完整性,如 switch 语句的默认分支。

总结

类型主要用途是否安全
any任意类型,但不安全×
unknown任意类型,但需要类型检查
never代码不会执行到的情况,如抛错或死循环

最佳实践:
尽量避免 any使用 unknown 进行安全检查never 确保代码完整性