【问题标题】:Typescript doesn't allow typeof inheritance of classes with different constructor signaturesTypescript 不允许对具有不同构造函数签名的类进行 typeof 继承
【发布时间】:2015-10-30 18:30:03
【问题描述】:

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

我终于找出了原因。在打字稿中,您不能定义参数arg typeof X 并传入构造函数Y,如果是'Y extends X 的事件。 构造函数必须具有相同的签名

检查sn-p。在底部,即使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

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

class DerivedClass extends BaseClass{
    constructor(b? : any);
    constructor(b : number) {
        super();
    }
}

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

谁能指出我如何摆脱这些编译器错误,而无需到处添加无用的重载签名的肮脏技巧?

【问题讨论】:

    标签: inheritance static compiler-errors typescript


    【解决方案1】:

    你在这里真正想说的是你想要一个BaseClass 的构造函数,它接受任意数量的参数。你可以写那种类型:

    class CommandBus {
        register(handler: new(...args: any[]) => BaseClass) {}
    }
    

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

    class CommandBus {
        register(handler : typeof BaseClass) {
           var x = new handler();
        }
    }
    var c = new CommandBus();
    c.register(DerivedClass);
    

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


    这几行

    commandBus.register(Function); // Compiles
    commandBus.register(Object); // Compiles
    

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

    【讨论】:

    • 非常感谢,成功了!
    • 但是为什么可以使用 register(handler : BaseClass) 并使用 register(derivedClassInstance) 而不能使用 register(handler : typeof BaseClass)register(DerivedClass) ? Typescript 不应该允许这种用法吗?我不深入了解打字稿,但直觉上这不是合乎逻辑的吗?可能是因为习惯了其他OO语言(Java、Pascal)的类可以传入。
    • 这是关于可替代性的——typeof DerivedClass 实际上不能替代typeof BaseClass,因为它需要额外的构造函数参数。根据相同的规则,如果您的派生类实例形状不可分配给基类实例类型,您可能收到register(derivedClassInstance) 错误。
    • 如果基类是抽象的,这将不起作用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-05
    • 2017-03-18
    • 1970-01-01
    • 1970-01-01
    • 2016-05-16
    • 1970-01-01
    相关资源
    最近更新 更多