有没有人在使用动态方法扩展类时获得类型检查的好方法?例如,假设您想使用基于传递给构造函数的选项的方法来扩展类。这在普通的 JavaScript 中很常见。
const defaults = {
dynamicMethods: ['method1', 'method2'];
};
class Hello {
constructor(options) {
options.dynamicMethods.forEach(m => this[m] = this.common);
}
private common(...args: any[]) {
// do something.
}
}
const hello = new Hello(defaults);
Run Code Online (Sandbox Code Playgroud)
当然,上面的方法会起作用,您将能够调用这些动态方法,但不会获得智能感知。
不是你可以用下面的东西来解决这个问题:
class Hello<T> {
constructor(options) {
options.dynamicMethods.forEach(m => this[m] = this.common);
}
private common(...args: any[]) {
// do something.
}
}
interface IMethods {
method1(...args: any[]);
method2(...args: any[]);
}
function Factory<T>(options?): T & Hello<T> {
const hello = new Hello<T>(options);
return hello as T & Hello<T>;
}
Run Code Online (Sandbox Code Playgroud)
消费这个:
import { Factory } from './some/path'
const hello = new Factory<IMethods>(defaults);
Run Code Online (Sandbox Code Playgroud)
这当然有效,但想知道还有其他替代方案!
在玩了一会儿之后,我想出了一些不需要为每个扩展声明接口的东西:
interface ClassOf<T> {
new(...args: any[]) : T
}
const extendClass = <T,S>(class_ : ClassOf<T>, dynamicMethods : S) =>
(...args: any[]) => {
const o = new class_(args) as T & S;
for (const key of Object.keys(dynamicMethods) as Array<keyof S>) {
const method = dynamicMethods[key];
(o as S)[key] = method; // type sig seems unnecessary
}
return o;
}
// demo:
class Hello {
constructor(public name) {}
hello() {
return 'hello ' + this.name;
}
}
const extHelloConstr = extendClass(Hello, {incr: (x : number) => x + 1, show: (n : number) => 'nr ' + n});
const extHello = extHelloConstr('jimmy');
const test1 = extHello.incr(1);
const test2 = extHello.show(42);
const test3 = extHello.hello();
console.log(test1, test2, test3);
Run Code Online (Sandbox Code Playgroud)
除了构造函数参数(看起来很棘手)之外,所有推断的类型都是正确的。它甚至在执行代码时也能工作。你也可以返回一个匿名类,但输入这些有点奇怪。
不确定这是否是您要找的东西,但也许它可以作为灵感的来源。
归档时间: |
|
查看次数: |
1898 次 |
最近记录: |