打字稿:类扩展了通用类型

时间:2018-07-28 02:14:23

标签: typescript

我知道它太通用了,但是我希望创建一个这样的类,该类将具有如下所示的通用类型的所有道具和原型:

class GenericExtend<T> extends T {
    constructor(data: T) {
        // here is a workaround to make these 2 classes unique
        const proto = { ...GenericExtend.prototype };
        Object.assign(proto, Object.getPrototypeOf(data));
        Object.setPrototypeOf(this, proto);
        Object.assign(this, data);
    }

    GenericMethod() { }
}

现在,我可以实例化GenericExtend类,然后获得两个类的类型,如下所示:

const obj = new GenericExtend<Model>(data);
obj.GenericMethod(); // ok
obj.ModelMethod(); // good!

我的解决方案之一是使用交集,如下所示:

const obj: GenericExtend & Model = new GenericExtend(data) as any;

它奏效了,但我不太喜欢。我能做些更好的事情吗?

2 个答案:

答案 0 :(得分:2)

我认为您必须使用交集来实现此行为...但是您可以根据需要将类型断言限制在构造函数中,这样以后的使用将不需要它。让我们重命名GenericExtend

class _GenericExtend<T> {
  constructor(data: T) {
    const proto = { ..._GenericExtend.prototype };
    Object.assign(proto, Object.getPrototypeOf(data));
    Object.setPrototypeOf(this, proto);
    Object.assign(this, data);
  }
  GenericMethod() { }
}

然后使用所需的交集行为将GenericExtend重新定义为类型和构造函数:

type GenericExtend<T> = _GenericExtend<T> & T;
const GenericExtend: new <T>(data: T) => GenericExtend<T> = _GenericExtend as any;

最后一个as any是我们需要的类型断言。现在您应该能够获得想要的行为:

interface Model {
  ModelMethod(): void;
}
declare const data: Model;

const obj = new GenericExtend(data);
obj.GenericMethod(); // ok
obj.ModelMethod(); // ok

希望有帮助。祝你好运!

答案 1 :(得分:0)

我遇到了类似的需求,最终按照以下方式实现,严格不需要交集(您可以定义专用类型进行类型检查),希望对您有所帮助。

class A {
  a() {
    ...
  }
}

class B {
  b() {
    ...
  }
}

type Constructor = new (...args: any[]) => any

function genericExtend<T extends Constructor>(target: T) {
  return class GenericExtended extends target {
    constructor(...args: any[]) {
      super(...args)
    }

    genericMethod() {
      ...
    }
  }
}

const instanceOfA: GenericExtended & A = new (genericExtend(A))()
const instanceOfB = new (genericExtend(B))()

instanceOfA.a() // ok with type checking
instanceOfA.genericMethod() // ok with type checking

instanceOfB.b() // ok without type checking
instanceOfB.genericMethod() // ok without type checking