一、typeof(在 TS 里是“取类型”)
⚠️ TS 的 typeof ≠ JS 的 typeof
| 场景 | JS typeof | TS 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 | symbol2️⃣ 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 联合