基于本文回答

播面 播面

刷题像听歌,多听自然懂
0
评论

any、unknown、never 和 void 之间有什么区别?

知识点图片

在 TypeScript 中,anyunknownnevervoid 都是特殊的类型,它们在类型系统中的地位和用途各不相同。

为了让你更直观地理解,我们可以把它们分为两组来对比:

  1. 包含一切的类型(Top Types): any vs unknown
  2. 表示“无”或“不可能”的类型: void vs never

以下是详细的区别解析:


1. any vs unknown (顶级类型)

这两个类型都可以接收任何值,但在使用这些值时,规则完全不同。

any (任意类型)

  • 定义: “我不在乎类型,请关闭类型检查。”
  • 特点: 它是类型系统的“逃生舱”。你可以把任何值赋给 any,也可以在 any 类型的变量上进行任何操作(调用方法、访问属性),TypeScript 编译器不会报错
  • 代价: 失去了 TypeScript 的类型保护,可能导致运行时错误。
typescript
let value: any = "hello";

value = 123;        // OK
value = true;       // OK
value.foo();        // OK (编译通过,但运行时会报错,因为 boolean 没有 foo 方法)
value();            // OK (编译通过,运行时报错)
const b: boolean = value; // OK (any 可以赋值给任何类型)

unknown (未知类型)

  • 定义: “我不知道这是什么类型,但在我确认之前,不允许你乱用。”
  • 特点: 它是 any类型安全版本。你可以把任何值赋给 unknown但是,你不能直接调用它的方法或访问属性,也不能把它赋值给其他具体类型的变量,除非你先进行类型收窄 (Type Narrowing)
typescript
let value: unknown = "hello";

value = 123;        // OK
value = true;       // OK

// value.foo();     // Error: 对象类型为 'unknown'
// value();         // Error
// const b: boolean = value; // Error: 不能把 'unknown' 分配给 'boolean'

// 正确用法:必须先检查类型
if (typeof value === 'string') {
    console.log(value.toUpperCase()); // OK,TS 知道这里它是 string
}

总结区别:

  • any不安全的,允许做任何事。
  • unknown安全的,在判断具体类型之前,禁止做任何事。

2. void vs never (返回类型)

这两个类型通常用于函数的返回值,表示函数“不返回正常值”的情况,但程度不同。

void (空)

  • 定义: “函数正常执行完了,但没有返回任何有意义的值。”
  • 特点: 在 JavaScript 中,如果函数没有 return,它默认返回 undefinedvoid 类型正是表示这种情况。
  • 赋值: 变量如果是 void 类型,只能被赋值为 undefined (如果 strictNullChecks 关闭,也可以是 null)。
typescript
function logMessage(msg: string): void {
    console.log(msg);
    // 函数执行完毕,隐含 return undefined
}

const result = logMessage("Hi"); // result 的类型是 void (实际值是 undefined)

never (永不)

  • 定义: “函数永远不会正常结束(无法到达终点)。”
  • 特点: 表示代码流程根本不可能执行到这里。它是所有类型的子类型(底层类型,Bottom Type)。
  • 场景:
    1. 抛出错误(异常中断)。
    2. 死循环(永远在运行)。
    3. 类型收窄时的“不可能情况”(Exhaustive Check)。
typescript
// 场景 1: 抛出错误
function throwError(msg: string): never {
    throw new Error(msg);
    // 代码永远不会执行到这里
}

// 场景 2: 死循环
function infiniteLoop(): never {
    while (true) {
    }
}

// 场景 3: 兜底检查 (Exhaustive Check)
type Direction = 'Up' | 'Down';
function check(dir: Direction) {
    if (dir === 'Up') {
        // ...
    } else if (dir === 'Down') {
        // ...
    } else {
        // 如果 dir 类型正确,这里永远不可达
        // const n: never = dir; 
    }
}

总结区别:

  • void:函数执行完,返回 undefined
  • never:函数不能正常执行完(报错或死循环),什么都不返回。

一张表总结

类型 含义 能赋值给它吗? 它能赋值给别人吗? 典型用途
any 任意 ✅ 是 (任何值) ✅ 是 (任何类型) 迁移旧代码、绕过类型检查 (尽量少用)
unknown 未知 ✅ 是 (任何值) ❌ 否 (仅能赋给 anyunknown) 替代 any,处理不确定的输入 (如 API 数据)
void ⚠️ 仅 undefined ❌ 否 函数没有返回值
never 不可能 ❌ 否 (除了 never 本身) ✅ 是 (所有类型) 抛错函数、死循环、类型守卫兜底

最佳实践建议

  1. 尽量避免使用 any:除非你在快速迁移 JS 代码,否则它会破坏 TS 的价值。
  2. 优先使用 unknown:当你不知道一个变量是什么类型时(例如 JSON.parse 的结果),用 unknown 强迫自己在使用前进行类型检查。
  3. 函数无返回值用 void:这是最常见的用法。
  4. 利用 never 做全面性检查:在 switch 语句的 default 分支使用 never,可以确保你处理了联合类型中的所有情况。
00:00
00:00