TypeScript 中的 keyof 与 typeof

📅
1 分钟阅读
·

背景

下面的 TypeScript 写法:

enum SOME_ENUM {
A = 1,
B = 2
}
type CodeType = typeof SOME_ENUM[keyof typeof SOME_ENUM];
type CodeType1 = (typeof SOME_ENUM)[keyof typeof SOME_ENUM];

这两个类型定义等价。下面分别说明这两个操作符的作用。

1. keyof 的作用

获取对象类型的键的联合类型

    interface Person {
      name: string;
      age: number;
    }
    type PersonKeys = keyof Person; // "name" | "age"

这常用于限制函数参数必须为对象的有效键:

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

2. typeof 的作用

获取变量或表达式的类型

const person = { name: "Alice", age: 30 };
type PersonType = typeof person; // { name: string; age: number }

当变量结构较复杂时,可以用它避免重复定义类型。

3. 结合使用 keyof 和 typeof

动态生成键的联合类型

const config = { host: "localhost", port: 8080 };
type ConfigKeys = keyof typeof config; // "host" | "port"

当 config 结构变化时,ConfigKeys 会自动更新。

4. 典型应用场景

  • 类型安全的对象操作: 限制函数只能访问对象的有效属性,避免拼写错误:
const obj = { id: 1, value: "test" };
function logKey(key: keyof typeof obj) {
	console.log(obj[key]);
}
logKey("id");    // 正确
logKey("name");  // 错误:类型不匹配
  • 映射类型和工具类型keyof 常用于构建映射类型,如内置的 Partial<T> 或自定义类型:
type Readonly<T> = {
    readonly [K in keyof T]: T[K];
};
  • 枚举键的提取: 获取枚举类型的键名字符串联合:
enum Direction { Up, Down }
type DirectionKeys = keyof typeof Direction; // "Up" | "Down"

5. 注意事项

  • 联合类型的 keyof: 对联合类型使用 keyof 会得到所有成员键的联合:
type A = { a: string } | { b: number };
type Keys = keyof A; // "a" | "b"
  • typeof 的上下文区分: 在类型上下文中使用 typeof(提取类型),而非值上下文中的 JavaScript typeof(返回类型字符串)

keyof 从类型中提取键的联合类型,typeof 从值中提取类型。二者组合后,可以生成与变量结构一致的键类型。


48 字 · 20 段落
ximing

Follow onGitHub

相关文章