带有可选超类的 Typescript 混合函数
Typescript mixin function with optional superClass
我正在尝试构建一个 可选 需要超级 class 的混合函数。基本原理是我们通常只构建中间 classes 来开始我们的混入。我对以下声明非常有信心,但是它们不起作用:
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;
}
您不能扩展条件类型,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
指定显式类型参数并省略该参数,它应该可以正常工作。
找到一个共同点——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";
}
}
我正在尝试构建一个 可选 需要超级 class 的混合函数。基本原理是我们通常只构建中间 classes 来开始我们的混入。我对以下声明非常有信心,但是它们不起作用:
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;
}
您不能扩展条件类型,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
指定显式类型参数并省略该参数,它应该可以正常工作。
找到一个共同点——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";
}
}