动态类方法

ori*_*ech 1 typescript

有没有人在使用动态方法扩展类时获得类型检查的好方法?例如,假设您想使用基于传递给构造函数的选项的方法来扩展类。这在普通的 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)

这当然有效,但想知道还有其他替代方案!

Obl*_*sys 5

在玩了一会儿之后,我想出了一些不需要为每个扩展声明接口的东西:

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)

游乐场链接

除了构造函数参数(看起来很棘手)之外,所有推断的类型都是正确的。它甚至在执行代码时也能工作。你也可以返回一个匿名类,但输入这些有点奇怪。

不确定这是否是您要找的东西,但也许它可以作为灵感的来源。

  • @kokodoko 我发现 Oblosys 代码完全可读。我认为这里的问题是这是一个高级问题,这里的许多评论似乎不理解这些更复杂的用例。不是在这里对你开枪,只是说这个例子没有任何问题。 (3认同)