打字稿不允许具有不同构造函数签名的类的类型继承

Lud*_*c C 7 inheritance static compiler-errors typescript

我正在实现一个 commandBus,我想用命令处理程序注册命令类型,以将传入的命令映射到正确的命令处理程序。我传递了一个命令构造函数来映射到像这样的处理程序构造函数register(handler : typeof Handler, command : typeof Command)。但我不断收到编译错误。

我终于查清了原因。在打字稿中,您不能定义参数arg typeof X并传入构造函数Y, event if ' Y extends X构造函数必须具有相同的签名

检查那个片段。在底部,甚至commandBus.register(Object)不会抛出编译错误。

class BaseClass{}
class DerivedClass extends BaseClass{
    constructor(b : number) {
        super();
    }
}
class AnotherClass extends BaseClass{
    constructor(){
        super();
    }
}
class CommandBus {
    register(handler : typeof BaseClass) {}
}
var commandBus = new CommandBus();
commandBus.register(DerivedClass); // Argument of type 'typeof DerivedClass' is not assignable to parameter of type 'typeof BaseClass'.
commandBus.register(AnotherClass); // Compiles
commandBus.register(Function); // Compiles
commandBus.register(Object); // Compiles
Run Code Online (Sandbox Code Playgroud)

我让它工作的唯一方法是添加一个重载构造函数签名

class DerivedClass extends BaseClass{
    constructor(b? : any);
    constructor(b : number) {
        super();
    }
}
Run Code Online (Sandbox Code Playgroud)

但这是我还是这该死的丑陋?

任何人都可以指出我如何摆脱这些编译器错误的方向,而不会到处添加无用的重载签名?

Rya*_*ugh 5

你在这里真正想说的是你想要一个带有BaseClass任意数量参数的构造函数。您可以编写该类型:

class CommandBus {
    register(handler: new(...args: any[]) => BaseClass) {}
}
Run Code Online (Sandbox Code Playgroud)

请注意,错误是 100% 正确的。如果你写过

class CommandBus {
    register(handler : typeof BaseClass) {
       var x = new handler();
    }
}
var c = new CommandBus();
c.register(DerivedClass);
Run Code Online (Sandbox Code Playgroud)

您将向DerivedClass构造函数传递零个参数。


这些线在这里

commandBus.register(Function); // Compiles
commandBus.register(Object); // Compiles
Run Code Online (Sandbox Code Playgroud)

只编译因为BaseClass没有成员(记住,TypeScript 使用结构类型系统,所以空类型可以任何类型分配!)。如果您添加任何BaseClass不在Function或 中的属性或方法Object,这些行就会成为错误。