TypeScript 核心类型与边界

any、unknown 与 never

any

any 会关闭后续类型检查,并且可以赋值给几乎任何类型。它适合迁移旧项目时作为临时逃生口,但不应成为默认方案。

let value: any = 'hello';
value.notExists().anything; // 编译器不会阻止

unknown

unknown 表示“类型暂时未知”。任何值都能赋给它,但使用前必须缩小类型,因此特别适合外部输入。

function parseError(error: unknown): string {
  if (error instanceof Error) return error.message;
  if (typeof error === 'string') return error;
  return 'Unknown error';
}

never

never 表示不可能出现的值,常用于永不返回的函数和穷尽检查。

type Status = 'idle' | 'loading' | 'success';

function assertNever(value: never): never {
  throw new Error(`Unexpected value: ${value}`);
}

function render(status: Status) {
  switch (status) {
    case 'idle': return '等待';
    case 'loading': return '加载中';
    case 'success': return '完成';
    default: return assertNever(status);
  }
}

新增联合类型成员后,漏掉分支会在编译期报错。

void、undefined 与 never

  • undefined 是一个具体值的类型。
  • void 表示调用方不应使用函数返回值,函数实际仍可能返回内容。
  • never 表示函数无法正常结束,例如始终抛错或无限循环。

类型断言不是类型转换

const input = document.querySelector('#name') as HTMLInputElement;

as 只影响编译器,不会在运行时检查或转换对象。外部数据仍需使用校验库或手写守卫验证。

type User = { id: number; name: string };

function isUser(value: unknown): value is User {
  if (typeof value !== 'object' || value === null) return false;
  const user = value as Record<string, unknown>;
  return typeof user.id === 'number' && typeof user.name === 'string';
}

object、Object 与 {}

  • object:非原始类型,通常最符合“对象”的语义。
  • Object:JavaScript 包装对象接口,原始值也可能满足,不推荐用作普通对象类型。
  • {}:除 nullundefined 外几乎所有值,不代表空对象。
  • Record<string, unknown>:更适合描述字符串键对象。

高频回答模板

对可信的内部数据使用明确类型;对接口、存储和用户输入先用 unknown 接收,再通过运行时校验缩小。any 只用于迁移边界,并配置 lint 防止扩散。