如何更新Object.defineProperty定义的JS/TS函数属性
TypeScript 场景下更新函数自定义属性方案
TypeScript编译报错来自静态类型校验:默认的Function类型定义中不存在你自定义的propertyOnFoo字段,属于类型层面的缺失,和JavaScript运行时行为无关。
你初始化属性时已经设置writable: true,JS运行时原生支持直接通过赋值修改属性值,完全不需要重复调用Object.defineProperty,直接赋值只会更新属性描述符内的value字段,不会替换整个属性描述对象。
方案1:补充函数类型定义(推荐,无运行时副作用)
通过类型合并给函数补充自定义属性的类型信息,整个逻辑仅在TS编译阶段生效,不会改动任何运行时代码,原有属性描述符会完整保留:
// 定义带自定义属性的函数类型:既符合原函数的调用签名,也携带自定义属性的类型 type FooWithCustomProp = { (): boolean; propertyOnFoo: string; }; // 初始化函数时做类型断言,给TS补充类型信息 const foo = function () { return true; } as FooWithCustomProp; // 原有Object.defineProperty逻辑无需改动 Object.defineProperty( foo, "propertyOnFoo", { value: "valueOnFoo", writable: true, configurable: true } ); // 直接赋值即可,无编译报错,运行时正常更新属性值 foo.propertyOnFoo = "updatedValue";
验证方式:赋值后调用
Object.getOwnPropertyDescriptor(foo, 'propertyOnFoo')打印,可看到除value更新为新值外,writable、configurable等配置和初始定义完全一致,没有替换整个属性描述对象。
方案2:局部类型断言(适合零散访问场景)
如果不需要全局给foo补充类型,仅在修改属性的位置做局部类型断言即可,同样无运行时副作用:
// 局部断言属性类型后修改 (foo as { propertyOnFoo: string }).propertyOnFoo = "newValue";
如果不需要保留类型校验,也可以临时断言为any,但会丢失类型安全,不推荐生产环境使用:
(foo as any).propertyOnFoo = "newValue";
注意事项
- 只有属性配置
writable: false时,直接赋值才会失败(非严格模式静默失败,严格模式抛出TypeError),当前场景的配置已经满足直接赋值的条件 - 不要通过重新调用
Object.defineProperty的方式更新值,会不必要地重写属性描述符,直接赋值是性能更好、逻辑更简洁的实现方式
内容的提问来源于stack exchange,提问作者Benjamin Cai
相关产品推荐
相关产品推荐

