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

如何实现TypeScript文档中的makeWatchedObject函数?

解决makeWatchedObject未定义的错误并实现TypeScript手册中的示例

TypeScript手册里的这段代码只包含类型定义(declare function仅用于告知TypeScript类型信息,没有实际运行逻辑),直接用Node运行会报ReferenceError,因为JavaScript环境中不存在该函数的实际实现。

以下是完全符合类型要求的可运行实现,通过Proxy拦截属性修改并触发对应回调:

type PropEventSource<Type> = {
    on<Key extends string & keyof Type>(
        eventName: `${Key}Changed`, 
        callback: (newValue: Type[Key]) => void
    ): void;
};

function makeWatchedObject<Type>(obj: Type): Type & PropEventSource<Type> {
    // 存储每个事件对应的回调列表
    const callbacks = new Map<string, Array<(value: unknown) => void>>();

    // 创建代理对象拦截属性设置操作
    const proxy = new Proxy(obj, {
        set(target, prop, newValue) {
            // 先更新目标对象的属性值
            (target as Record<string, unknown>)[prop as string] = newValue;
            // 触发对应的XXXChanged事件回调
            const eventName = `${prop}Changed`;
            callbacks.get(eventName)?.forEach(callback => callback(newValue));
            return true;
        }
    });

    // 为代理对象挂载on方法,用于注册事件回调
    (proxy as Type & PropEventSource<Type>).on = <Key extends string & keyof Type>(
        eventName: `${Key}Changed`,
        callback: (newValue: Type[Key]) => void
    ) => {
        if (!callbacks.has(eventName)) {
            callbacks.set(eventName, []);
        }
        callbacks.get(eventName)!.push(callback);
    };

    return proxy as Type & PropEventSource<Type>;
}

// 测试代码
const person = makeWatchedObject({
    firstName: "Saoirse",
    lastName: "Ronan",
    age: 26
});

person.on("firstNameChanged", newName => {
    console.log(`new name is ${newName.toUpperCase()}`);
});

person.on("ageChanged", newAge => {
    if (newAge < 0) {
        console.warn("warning! negative age");
    }
});

// 修改属性触发回调
person.firstName = "Emily"; // 输出:new name is EMILY
person.age = -1; // 输出:warning! negative age

实现核心逻辑:

  • 用Proxy拦截对象的set操作,当属性被修改时自动触发对应XXXChanged事件的回调
  • 用Map存储每个事件对应的回调函数列表,实现多回调注册
  • 为代理对象扩展on方法,完成回调的注册逻辑

将代码保存为.ts文件后,可通过tsc编译为JavaScript再用Node运行,或直接用ts-node执行即可正常运行。

内容的提问来源于stack exchange,提问作者ShouGuouo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 13:00:56