动态添加接口方法

时间:2019-11-18 13:57:25

标签: typescript

我想动态添加接口中定义的方法。我以为索引签名将是必经之路,但可悲的是,并非所有方法都适合同一签名。我的目标是保留所有类型信息。

基本代码,由于尚未实现所有方法,因此当前无法编译。当我添加Partial时,代码可以编译,但是我似乎丢失了类型信息。

import anotherLib from "anotherLib";

interface IALotOfMethods<T> {
  methodA(): T;
  methodB(opts: MyOpts): T;
  ...
}

interface IMyClass<T> extends IALotOfMethods<T> {
  getName(): string;
  getSomething(): number;
}

class MyClass implements IMyClass<MyClass> {
  results: any[] = [];

  getName(): string {
    return "A Name";
  }

  getSomething(): number {
    return 0;
  }
}

const aLotOfMethodsList = ['methodA', 'methodB', ...];

aLotOfMethodsList.forEach(funcName => {
  MyClass.prototype[funcName] = function(opts: any) {
    this.results.push(anotherLib[funcName](opts));
    return this;
  }
})

const myObj = new MyClass();
myObj.methodA(); // methodA should be available/autosuggested

这可能吗?即使它们基本上看起来都一样,我是否需要手动实现所有方法?我需要放弃类型信息吗?

谢谢

1 个答案:

答案 0 :(得分:1)

here也使用的一种解决方案是将类和接口与可选属性合并。

interface Component {
   optionalMethod?(l: GetLocalization): void;
}
abstract class Component {
    public abstract mustImplement(): void;
}

class Post extends Component {
    public mustImplement(): void {}
}

在您的情况下:Stackblitz

自动完成有效,但是您可能会收到“无法调用未定义的方法”警告,因此您必须确定自己在做什么

编辑:如果不进行双重合并,甚至更好

import anotherLib from "anotherLib";

abstract class Component<T> {
    methodA?(): T;
    methodB?(opts: string): T;
    public abstract mustImplement(): void;
}

class Post extends Component<string> {
    public mustImplement(): void {
    }
}

const aLotOfMethodsList = ['methodA', 'methodB'];

aLotOfMethodsList.forEach(funcName => {
  (Post as any).prototype[funcName] = function(opts: any) {
    this.results.push(anotherLib[funcName](opts));
    return this;
  }
})

const myObj = new Post();
myObj.methodA(); // autocomplete