I am implementing a commandBus, and I want to register command types with command handlers to map incoming commands to the right command handler. I passed a command constructor to map to a handler constructor like so register(handler : typeof Handler, command : typeof Command)
. But I kept getting compilaton errors.
I finally isolated the reason. In typescript, you can't define an argument arg typeof X
and pass in a constructor Y
, event if 'Y extends X
. The constructors must have the same signature.
Check that snippet. At the bottom, even commandBus.register(Object)
does not throw compilation errors.
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
The only way I got this to work is to add an overload constructor signature
class DerivedClass extends BaseClass{
constructor(b? : any);
constructor(b : number) {
super();
}
}
But is it me or this is damn ugly?
Can anyone point me into a direction on how to get rid of these compiler errors without a dirty hack of adding useless overload signature all over the place?
What you're really trying to say here is that you want a constructor function for a BaseClass
that takes any number of arguments. You can write that type:
class CommandBus {
register(handler: new(...args: any[]) => BaseClass) {}
}
Note that the error is 100% correct. If you had written
class CommandBus {
register(handler : typeof BaseClass) {
var x = new handler();
}
}
var c = new CommandBus();
c.register(DerivedClass);
You'd be passing zero arguments to the DerivedClass
constructor.
These lines down here
commandBus.register(Function); // Compiles
commandBus.register(Object); // Compiles
only compile because BaseClass
has no members (remember, TypeScript uses a structural type system, so the empty type is assignable from any type!). If you add any properties or methods to BaseClass
that aren't in Function
or Object
, these lines become errors.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With