需要类以基于泛型的参数实现方法

时间:2019-06-30 02:09:00

标签: typescript decorator typescript-generics typescript-decorator

我有一个ClassDecorator,它使用未指定数量的构造函数参数(<T>: { new (...args: any[]) => T }),并基于此,我希望该类要求实现一个具有与提供的构造函数类型相同的参数的方法。

我的装饰师

type Constructor<T> = new (...args: any[]) => T;
type ComponentArray = Array<Constructor<unknown>>;

export interface TSystem<TComps extends ComponentArray> {
  handle: (...comps: TComps) => void;
}


export function System<TComps extends ComponentArray>(...comps: TComps) {
  return (ctor: Constructor<Required<TSystem<TComps>>>) => {
     // add metadata etc...
  };
}

示例:


class RandomComponent {
  test1: string;
  // implementation ...
}

class RandomComponent2 {
  test2: string;
  // implementation ...
}

@System(RandomComponent, RandomComponent2 /* etc ... */)
class TestSystem {
  handle(r1: RandomComponent, r2: RandomComponent2 /* etc... */) {
    // handle components ...
  }
}

我希望这会起作用,但是编译器给我这个错误:

Type '(comp: RandomComponent) => void' is not assignable 
to type '(comps_0: typeof RandomComponent) => void' 

有没有一种方法可以从TSystem接口中删除typeof,或者可以通过其他方式完成此操作?我想访问Class的实例,而不是其类型。还是这仅仅是TypeScript类型系统的局限性?

1 个答案:

答案 0 :(得分:2)

该代码在3.5.1上对我有效,我将其发布在这里,您能否更新错误所在的问题,并更新我的答案。您使用Typescript肯定可以is描述什么。

https://typescript-play.js.org/?experimentalDecorators=true#code/C4TwDgpgBAwg9gOwM7AE4FcDGw6oDwAqAfFALxQIQDuUAFAHSMCGqA5kgFxRMIgDaAXQCUZEgQDcAKFCRYcALZhEEBMACCqVExBkoGrSDzoEAawRwqCIlMkQAHktTAoAS1URUAMyaZoBAMogKBDyhPCKSFD2wCoAJpHhSpSq+tokAN6SUFAAFjyxADYQXAyMmApgnFAEiUgipCQAbnAusVIAvpJd9o7OnsbYLohQgcGhNRWR0XEJFcopmmml9OURXBMRIpnZqBDA6KgIdNi4XPDIaFg4+ABKEACO6C67sYSjMeO1RN-1GVnZ2QA9IDuLFYlB5HsmLEmMAmFFgJhGPR-u0Ol1MAUmEhIjd8gpEvNnNsoMC5Ioia5FEVIapYUMEJJOpIAALvEK0PEIWIEubJYBCSSY7GRAgQFDs+RQEl5blFWirMBcLk8+SE-lbUkgqi4ExIf5AkHIqKxFzORWoplAA

编辑: 更改此行

  handle(comp: typeof RandomComponent) 

我很确定应该按照您想要的内容进行操作。

EDIT2:我想这就是您想要的。

type Constructor<T> = new (...args: any[]) => T;
type ComponentArray = Array<Constructor<unknown>>;

export interface TSystem<TComps extends ComponentArray> {
  handle: (...comps: ConvertInstanceTypes<TComps>) => void;
}

type ConvertInstanceTypes<T extends any[]> = {
  [K in keyof T]: T[K] extends Constructor<any> ? InstanceType<T[K]> : never;
}


export function System<TComps extends ComponentArray>(...comps: TComps) {
  return (ctor: Constructor<Required<TSystem<TComps>>>) => {
     // add metadata etc...
  };
}

class RandomComponent {
  test1: string = "test1";
  // implementation ...
}

class RandomComponent2 {
  test2: string = "test2";
  // implementation ...
}


@System(RandomComponent, RandomComponent2)
class TestSystem {
  handle(r1: InstanceType<typeof RandomComponent>, r2: InstanceType<typeof RandomComponent2>) {
    // handle components ...
  }
}