TypeScript中如何将接口转换为映射类型?proxify函数实现疑问
如何实现TypeScript官方示例中的proxify函数?
我来帮你拆解一下这个proxify函数的实现思路,其实核心就是把原对象的每个属性都包装成带get()和set(value: T)方法的代理结构,同时严格贴合TypeScript的映射类型约束。
首先先回顾官方给出的类型定义:
type Proxy<T> = { get(): T; set(value: T): void; } type Proxify<T> = { [P in keyof T]: Proxy<T[P]>; }
Proxify<T>会把传入类型T的每个属性都转换成对应的Proxy类型,我们的proxify函数要做的就是把实际对象的属性逐个包装成符合这个类型的结构。
基础版proxify实现
这里我们可以用闭包来维护每个属性的内部值,然后为每个属性生成对应的get和set方法:
function proxify<T>(o: T): Proxify<T> { // 创建一个空对象作为返回结果,先断言为Proxify<T>避免类型报错 const result = {} as Proxify<T>; // 遍历原对象的所有属性键 for (const key in o) { // 用闭包保存当前属性的内部值 let internalValue = o[key]; // 为当前属性创建Proxy结构 result[key] = { get: () => internalValue, set: (value) => { internalValue = value; // 这里可以额外加一些逻辑,比如值变更的通知 console.log(`Property ${key} updated to ${value}`); } }; } return result; }
结合你的实际User接口场景
假设你的实际类型定义是这样的(补全你提到的readonly属性):
interface BaseRecord { // 假设BaseRecord有一些基础属性 createdAt: Date; } interface User extends BaseRecord { readonly id: number; readonly name: string; age: number; email: string; }
对于readonly属性,我们可以在set方法里做限制,比如禁止修改,保持原属性的只读特性:
function proxify<T>(o: T): Proxify<T> { const result = {} as Proxify<T>; for (const key in o) { let internalValue = o[key]; // 判断当前属性是否是readonly(通过原对象的属性描述符) const isReadonly = Object.getOwnPropertyDescriptor(o, key)?.writable === false; result[key] = { get: () => internalValue, set: (value) => { if (isReadonly) { console.warn(`Cannot modify readonly property ${key}`); return; } internalValue = value; console.log(`Property ${key} updated to ${value}`); } }; } return result; } // 测试使用 const user: User = { id: 1, name: "Christian Ravn", age: 30, email: "example@test.com", createdAt: new Date() }; const proxiedUser = proxify(user); console.log(proxiedUser.id.get()); // 输出1 proxiedUser.id.set(2); // 输出警告:Cannot modify readonly property id proxiedUser.age.set(31); // 输出:Property age updated to 31 console.log(proxiedUser.age.get()); // 输出31
这样实现的proxify函数既符合官方类型定义的要求,又能适配你实际业务中带readonly属性的接口场景。
内容的提问来源于stack exchange,提问作者Christian Ravn
相关产品推荐
相关产品推荐

