TypeScript 中的 typeof 和 keyof 是非常强大的类型操作符,它们可以单独使用,也可以组合使用来创建复杂的类型。以下是一些高级应用案例:
- 使用
typeof获取变量的类型
const user = {
name: "John",
age: 30,
email: "john@example.com"
};
type User = typeof user;
// User 类型等同于:
// {
// name: string;
// age: number;
// email: string;
// }- 使用
keyof获取对象的键类型
interface Person {
name: string;
age: number;
address: string;
}
type PersonKeys = keyof Person; // "name" | "age" | "address"- 结合
typeof和keyof创建对象的键类型
const colors = {
red: "#FF0000",
green: "#00FF00",
blue: "#0000FF"
};
type ColorKeys = keyof typeof colors; // "red" | "green" | "blue"- 创建类型安全的对象访问函数
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 的属性- 创建映射类型
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;
// }- 条件类型与
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; }- 递归类型与
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;
// };
// };
// }- 使用
typeof和keyof创建类型安全的事件系统
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" 不是有效的事件这些例子展示了 typeof 和 keyof 在 TypeScript 中的强大功能。它们可以帮助我们创建更加类型安全和灵活的代码,特别是在处理复杂的对象类型和泛型时非常有用。