TypeScript 中的 typeofkeyof 是非常强大的类型操作符,它们可以单独使用,也可以组合使用来创建复杂的类型。以下是一些高级应用案例:

  1. 使用 typeof 获取变量的类型
const user = {
  name: "John",
  age: 30,
  email: "john@example.com"
};
 
type User = typeof user;
 
// User 类型等同于:
// {
//   name: string;
//   age: number;
//   email: string;
// }
  1. 使用 keyof 获取对象的键类型
interface Person {
  name: string;
  age: number;
  address: string;
}
 
type PersonKeys = keyof Person; // "name" | "age" | "address"
  1. 结合 typeofkeyof 创建对象的键类型
const colors = {
  red: "#FF0000",
  green: "#00FF00",
  blue: "#0000FF"
};
 
type ColorKeys = keyof typeof colors; // "red" | "green" | "blue"
  1. 创建类型安全的对象访问函数
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}
 
const person = {
  name: "Alice",
  age: 25
};
 
const name = getProperty(person, "name"); // 类型为 string
const age = getProperty(person, "age");   // 类型为 number
// getProperty(person, "gender");         // 编译错误,"gender" 不是 person 的属性
  1. 创建映射类型
type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};
 
interface Mutable {
  a: number;
  b: string;
}
 
type ReadonlyMutable = Readonly<Mutable>;
 
// ReadonlyMutable 等同于:
// {
//   readonly a: number;
//   readonly b: string;
// }
  1. 条件类型与 keyof
type PickByType<T, U> = {
  [P in keyof T as T[P] extends U ? P : never]: T[P]
};
 
interface Mixed {
  a: string;
  b: number;
  c: boolean;
  d: string;
}
 
type StringProperties = PickByType<Mixed, string>; // { a: string; d: string; }
  1. 递归类型与 keyof
type DeepReadonly<T> = {
  readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P];
};
 
interface NestedObject {
  a: string;
  b: {
    c: number;
    d: {
      e: boolean;
    };
  };
}
 
type DeepReadonlyNested = DeepReadonly<NestedObject>;
 
// DeepReadonlyNested 等同于:
// {
//   readonly a: string;
//   readonly b: {
//     readonly c: number;
//     readonly d: {
//       readonly e: boolean;
//     };
//   };
// }
  1. 使用 typeofkeyof 创建类型安全的事件系统
const eventHandlers = {
  click: (x: number, y: number) => void 0,
  keypress: (key: string) => void 0,
  mousemove: (x: number, y: number) => void 0
};
 
type EventHandlers = typeof eventHandlers;
 
function addEventListener<K extends keyof EventHandlers>(
  event: K,
  handler: EventHandlers[K]
) {
  // 实现省略
}
 
addEventListener("click", (x, y) => console.log(x, y));
addEventListener("keypress", (key) => console.log(key));
// addEventListener("scroll", () => {});  // 编译错误,"scroll" 不是有效的事件

这些例子展示了 typeofkeyof 在 TypeScript 中的强大功能。它们可以帮助我们创建更加类型安全和灵活的代码,特别是在处理复杂的对象类型和泛型时非常有用。