跳转到内容
创建时间: 2020年12月5日

一、typeof(在 TS 里是“取类型”) ​

⚠️ TS 的 typeof ≠ JS 的 typeof

场景JS typeofTS typeof
作用运行时编译期
返回字符串类型

1️⃣ 基本用法 ​

ts
const user = {
  id: 1,
  name: "Tom",
  age: 18,
};

type User = typeof user;

等价于:

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

📌 核心用途:从“值”反推“类型”

2️⃣ 常见使用场景 ​

✅ 场景 1:配置对象 → 类型自动同步 ​

ts
const config = {
  mode: "dark",
  size: "small",
};

type Config = typeof config;

你改 config,类型自动变,不会不同步 👍

✅ 场景 2:函数 / hook 返回值类型 ​

ts
function useUser() {
  return {
    name: "Tom",
    age: 18,
  };
}

type User = ReturnType<typeof useUser>;

(typeof + 工具类型是王炸)

二、keyof(取对象的 key) ​

1️⃣ 基本用法 ​

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

type UserKeys = keyof User;

结果:

ts
type UserKeys = "id" | "name" | "age";

📌 keyof = 把 key 变成联合类型

2️⃣ keyof 的实际价值 ​

✅ 限制参数只能是对象的 key ​

ts
function getValue<T, K extends keyof T>(obj: T, key: K) {
  return obj[key];
}

getValue(user, "name"); // ✅
getValue(user, "xxx"); // ❌

这是 TS 类型安全的核心能力之一。

三、typeof + keyof(组合拳) ​

1️⃣ 从“对象值”中拿 key ​

ts
const user = {
  id: 1,
  name: "Tom",
  age: 18,
};

type UserKeys = keyof typeof user;

结果:

ts
"id" | "name" | "age";

📌 这是最常见的写法

2️⃣ 替代 enum(前端强烈推荐) ​

ts
const STATUS = {
  PENDING: "pending",
  SUCCESS: "success",
  ERROR: "error",
} as const;

type Status = (typeof STATUS)[keyof typeof STATUS];

结果:

ts
type Status = "pending" | "success" | "error";

💥 Vue / React 状态管理标配写法

四、进阶:as const 的重要性(必懂) ​

❌ 没有 as const ​

ts
const user = {
  role: "admin",
};

type Role = typeof user.role;
// string ❌

✅ 使用 as const ​

ts
const user = {
  role: "admin",
} as const;

type Role = typeof user.role;
// 'admin' ✅

📌 结论:

想拿「字面量类型」,一定要 as const

五、keyof 的常见变体 ​

1️⃣ keyof any ​

ts
type Keys = keyof any;
// string | number | symbol

2️⃣ keyof + 映射类型 ​

ts
type ReadonlyObj<T> = {
  readonly [K in keyof T]: T[K];
};

这是 Readonly<T> 的底层原理。

六、真实前端场景示例 ​

1️⃣ React props 校验 ​

ts
const props = {
  size: "small",
  type: "primary",
} as const;

type Props = typeof props;
type PropKeys = keyof Props;

2️⃣ Vue emit 事件 ​

ts
const emits = {
  submit: (value: string) => true,
  cancel: () => true,
};

type EmitName = keyof typeof emits;
// 'submit' | 'cancel'

3️⃣ 表单字段约束 ​

ts
type Form = {
  username: string;
  password: string;
};

function updateField(key: keyof Form, value: string) {}

七、常见坑总结(面试必问) ​

❌ keyof 用在值上

ts
keyof user // ❌
keyof typeof user // ✅

❌ typeof 不能用在类型上

ts
type A = { a: number };
type B = typeof A; // ❌

❌ 忘了 as const

ts
const arr = ["a", "b"];
type A = (typeof arr)[number]; // string ❌
ts
const arr = ["a", "b"] as const;
type A = (typeof arr)[number]; // 'a' | 'b' ✅

八、一句话记忆法 🧠 ​

  • typeof:从值 → 类型
  • keyof:从类型 → key 联合
  • typeof + keyof:从对象 → key 联合