keyof和typeof
# 一、typeof(在 TS 里是“取类型”)
⚠️ TS 的 typeof ≠ JS 的 typeof
| 场景 | JS typeof | TS typeof |
|---|---|---|
| 作用 | 运行时 | 编译期 |
| 返回 | 字符串 | 类型 |
# 1️⃣ 基本用法
const user = {
id: 1,
name: 'Tom',
age: 18
}
type User = typeof user
1
2
3
4
5
6
7
2
3
4
5
6
7
等价于:
type User = {
id: number
name: string
age: number
}
1
2
3
4
5
2
3
4
5
📌 核心用途:从“值”反推“类型”
# 2️⃣ 常见使用场景
# ✅ 场景 1:配置对象 → 类型自动同步
const config = {
mode: 'dark',
size: 'small'
}
type Config = typeof config
1
2
3
4
5
6
2
3
4
5
6
你改 config,类型自动变,不会不同步 👍
# ✅ 场景 2:函数 / hook 返回值类型
function useUser() {
return {
name: 'Tom',
age: 18
}
}
type User = ReturnType<typeof useUser>
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
(typeof + 工具类型是王炸)
# 二、keyof(取对象的 key)
# 1️⃣ 基本用法
type User = {
id: number
name: string
age: number
}
type UserKeys = keyof User
1
2
3
4
5
6
7
2
3
4
5
6
7
结果:
type UserKeys = 'id' | 'name' | 'age'
1
📌 keyof = 把 key 变成联合类型
# 2️⃣ keyof 的实际价值
# ✅ 限制参数只能是对象的 key
function getValue<T, K extends keyof T>(obj: T, key: K) {
return obj[key]
}
getValue(user, 'name') // ✅
getValue(user, 'xxx') // ❌
1
2
3
4
5
6
2
3
4
5
6
这是 TS 类型安全的核心能力之一。
# 三、typeof + keyof(组合拳)
# 1️⃣ 从“对象值”中拿 key
const user = {
id: 1,
name: 'Tom',
age: 18
}
type UserKeys = keyof typeof user
1
2
3
4
5
6
7
2
3
4
5
6
7
结果:
'id' | 'name' | 'age'
1
📌 这是最常见的写法
# 2️⃣ 替代 enum(前端强烈推荐)
const STATUS = {
PENDING: 'pending',
SUCCESS: 'success',
ERROR: 'error'
} as const
type Status = typeof STATUS[keyof typeof STATUS]
1
2
3
4
5
6
7
2
3
4
5
6
7
结果:
type Status = 'pending' | 'success' | 'error'
1
💥 Vue / React 状态管理标配写法
# 四、进阶:as const 的重要性(必懂)
# ❌ 没有 as const
const user = {
role: 'admin'
}
type Role = typeof user.role
// string ❌
1
2
3
4
5
6
2
3
4
5
6
# ✅ 使用 as const
const user = {
role: 'admin'
} as const
type Role = typeof user.role
// 'admin' ✅
1
2
3
4
5
6
2
3
4
5
6
📌 结论:
想拿「字面量类型」,一定要
as const
# 五、keyof 的常见变体
# 1️⃣ keyof any
type Keys = keyof any
// string | number | symbol
1
2
2
# 2️⃣ keyof + 映射类型
type ReadonlyObj<T> = {
readonly [K in keyof T]: T[K]
}
1
2
3
2
3
这是 Readonly<T> 的底层原理。
# 六、真实前端场景示例
# 1️⃣ React props 校验
const props = {
size: 'small',
type: 'primary'
} as const
type Props = typeof props
type PropKeys = keyof Props
1
2
3
4
5
6
7
2
3
4
5
6
7
# 2️⃣ Vue emit 事件
const emits = {
submit: (value: string) => true,
cancel: () => true
}
type EmitName = keyof typeof emits
// 'submit' | 'cancel'
1
2
3
4
5
6
7
2
3
4
5
6
7
# 3️⃣ 表单字段约束
type Form = {
username: string
password: string
}
function updateField(key: keyof Form, value: string) {}
1
2
3
4
5
6
2
3
4
5
6
# 七、常见坑总结(面试必问)
❌ keyof 用在值上
keyof user // ❌
keyof typeof user // ✅
1
2
2
❌ typeof 不能用在类型上
type A = { a: number }
type B = typeof A // ❌
1
2
2
❌ 忘了 as const
const arr = ['a', 'b']
type A = typeof arr[number] // string ❌
1
2
2
const arr = ['a', 'b'] as const
type A = typeof arr[number] // 'a' | 'b' ✅
1
2
2
# 八、一句话记忆法 🧠
- typeof:从值 → 类型
- keyof:从类型 → key 联合
- typeof + keyof:从对象 → key 联合
上次更新: 2026/01/07, 09:20:46