【发布时间】:2020-08-25 14:27:01
【问题描述】:
我对 Typescript 比较陌生。似乎带有泛型的混合是一个问题,我很快就遇到了它。考虑以下示例:
(编辑:将 Titian 的答案整合到方法 2 中并添加 setValue() 以更好地说明新问题。)
class A<T> {
public constructor(public a: T) {}
public setValue(a: T): void {this.a = a;}
}
class B<T> extends A<T> {public constructor(public a: T, public b: T) {super(a);}}
// approach 1
function mixinC(Base: ???) { // ??? = typeof A vs. ??? = typeof B vs. ??? = any
return class CMixin<T> extends Base<T> {}; //...
}
// approach 2
type Constructor<T> = new (...args: any[]) => T;
function mixinC<T extends Constructor<A<unknown>>>(Base: T) {
return class CMixin extends Base {}; //...
}
// test 1
class C<T> extends mixinC(A)<T> {}
interface C<T> extends A<T> {}
const c = new C<string>('123');
c.setValue(7); // no error, although 7 is not string
console.log(c.a);
// test 2
class D<T> extends mixinC(B)<T> {}
interface D<T> extends B<T> {}
const d = new D<string>('465', '789');
console.log(d.a, d.b);
我希望这两种测试都有效,但两种方法都无效。
如果有办法动态告诉编译器Base 将是typeof A 还是typeof B,第一种方法会起作用(我认为),但mixinC<T>(Base: typeof T) 不起作用,因为 T 是一个类型而不是一个值。我也试过any作为类型;这似乎在表面上起作用,但我可以访问C 的每个实例上的任意未定义属性(例如c.xyz)。
第二种方法原则上与ES6 Mixin with generic type in TypeScript 非常相似,但主要区别在于A(与那里的BaseClass 相当)是一个泛型类型。那我应该换什么???和?如果我可以使用参数类型T2 执行??? = A<T2>,也许它会起作用,但是我应该在哪里定义这个参数?
@edit:c.setValue(7); 可能不会引发错误,因为现在实际上存在两个版本的 setValue:string 一个(正确的)和一个 @987654338 @ one,后者允许7。
【问题讨论】:
标签: typescript generics mixins