You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:16:33