我正在尝试构建一个可选需要一个超类的mixin函数。这样做的理由是,我们通常只是建立中间类以从我们的mixins开始。我对以下声明很有信心,但是它们不起作用:
interface Test {
readonly __TEST: "test";
new (...args: any[]): {
readonly test: "test";
};
}
function TestMixin<SuperClass extends new (...args: any[]) => any>(
superClass?: SuperClass
) {
const defaultClass = class {};
/* Error: Type 'new (...args: any[]) => any' is not assignable to type 'SuperClass extends undefined ? typeof defaultClass : undefined'.ts(2322) */
const sc: typeof superClass extends undefined ? typeof defaultClass : undefined = superClass === undefined ? defaultClass : superClass;
/* Error: Type 'SuperClass extends undefined ? typeof defaultClass : undefined' is not a constructor function type. */
class T extends sc implements InstanceType<Test> {
public static readonly __TEST = "test";
public readonly test = "test";
}
return T;
}
答案 0 :(得分:1)
您不能扩展条件类型,Typescripts希望extends
子句中的子句是构造函数,而不是其他任何更复杂的类型。
我认为在这种情况下,最简单的解决方案是使用类型断言来欺骗编译器:
interface Test {
readonly __TEST: "test";
new(...args: any[]): {
readonly test: "test";
};
}
function TestMixin<SuperClass extends new (...args: any[]) => any = new () => {}>(
superClass?: SuperClass
) {
const defaultClass = class { };
/* ok */
const sc = (superClass === undefined ? defaultClass : superClass) as SuperClass;
/* Ok now */
class T extends sc implements InstanceType<Test> {
public static readonly __TEST = "test";
public readonly test = "test";
}
return T;
}
let a = TestMixin();
new a().test;
let b = TestMixin(class {
constructor(n: number) { console.log("Hi") }
m() { }
});
new b(1).test;
new b(1).m();
只要没有人为TestMixin
指定显式类型参数并省略该参数,它就可以正常工作。
答案 1 :(得分:0)
找到一个共同的分母-Constructor
类型。
interface Constructor<T = any> {
new (...args: any[]): T;
}
interface Test {
readonly __TEST: "test";
new(...args: any[]): {
readonly test: "test";
};
}
interface Constructor<T = any> {
new (...args: any[]): T;
}
function TestMixin<SuperClass extends new (...args: any[]) => any>(
superClass?: SuperClass
) {
const defaultClass: Constructor = superClass || class { };
return class T extends defaultClass implements InstanceType<Test> {
public static readonly __TEST = "test";
public readonly test = "test";
}
}