TypeScript如何按引用传递函数类型成员变量?
解决函数类型成员变量的Setter封装问题
当前代码中setDelegateToPrint无法修改myFoo.delegated,本质原因是JS/TS中函数参数按值传递:你传入的myFoo.delegated是当前函数引用的副本,在函数内部修改delegate变量只是改变了局部变量的指向,完全不会影响原对象的属性。
要求是Setter函数不能依赖Foo类的具体定义,只需要知道存在符合签名的成员函数,以下是两种可行方案:
方案一:传递属性设置回调
让调用者传入一个能修改目标属性的回调函数,Setter只负责把目标函数传递给这个回调,完全不需要知晓对象的具体类型:
class Foo { public delegated: (param: string) => void = () => { console.log("Default value, was not set to anything else."); }; } function printAllCaps(s: string): void { console.log(s.toUpperCase()); } // 接收一个设置回调,直接传递目标函数 function setDelegateToPrint(setter: (fn: (param: string) => void) => void) { setter(printAllCaps); } let myFoo: Foo = new Foo(); // 传入修改myFoo.delegated的回调 setDelegateToPrint((fn) => { myFoo.delegated = fn; }); myFoo.delegated("hello!"); // 输出 HELLO!
方案二:使用类型约束定义通用对象类型
定义一个接口描述拥有指定签名delegated属性的对象,Setter接收这个接口类型的参数,既保证类型安全,又不需要依赖具体的Foo类:
// 定义通用接口,描述符合要求的对象结构 interface HasStringDelegate { delegated: (param: string) => void; } class Foo { public delegated: (param: string) => void = () => { console.log("Default value, was not set to anything else."); }; } function printAllCaps(s: string): void { console.log(s.toUpperCase()); } // 接收符合HasStringDelegate接口的对象,直接修改其delegated属性 function setDelegateToPrint(obj: HasStringDelegate) { obj.delegated = printAllCaps; } let myFoo: Foo = new Foo(); setDelegateToPrint(myFoo); // Foo自动满足HasStringDelegate接口 myFoo.delegated("hello!"); // 输出 HELLO!
两种方案的对比
- 方案一更灵活:适用于无法直接访问对象属性的场景,或者属性设置需要额外逻辑的情况
- 方案二更直观:代码更简洁,适合常规的属性赋值场景
内容的提问来源于stack exchange,提问作者goose_lake
相关产品推荐
相关产品推荐

