Why does TypeScript complain about this code ?
class FooError extends Error {
}
const map = new Map<ErrorConstructor, any> ([
[Error, 'do this'],
[FooError, 'do that']
])
Type 'typeof FooError' is not assignable to type 'ErrorConstructor'.
Well, let's look at the definition of ErrorConstructor
:
interface ErrorConstructor {
new(message?: string): Error; // is a constructor
(message?: string): Error; // is callable
readonly prototype: Error; // has an Error prototype
}
So, an ErrorConstructor
needs to be a constructor which takes an optional string argument, and it also needs to be callable as a function, and it needs to have an Error
prototype. Let's look at your FooError
class:
class FooError extends Error {
}
FooError.prototype; // okay, type FooError
new FooError("okay"); // okay
FooError("oops"); // error
It has a FooError
prototype, which is fine since FooError
is a subtype of Error
. It is a constructor, and it does accept an argument since it defers to the superclass Error
, which is an ErrorConstructor
. But it's not callable as a function. So FooError
is not an ErrorConstructor
.
At this point, you need to decide if you actually care about it being an ErrorConstructor
. Do you plan to call it as FooError('msg')
instead of new FooError('msg')
? I doubt it. For that matter, do you care that the constructor's prototype
is of type FooError
? Probably not. In that case, don't use ErrorConstructor
. Instead, use the following interface which only cares about being an optional-one-string-arg constructor:
interface NoFrillsErrorConstructor {
new(message?: string): Error;
}
Now your code will work:
const map = new Map<NoFrillsErrorConstructor, any> ([
[Error, 'do this'],
[FooError, 'do that']
])
And all will be well, as long as you only use the map's keys as constructors:
map.forEach((val, err) => {
err.prototype; // exists, but is type any. Who cares, right?
new err(); // okay
err(); // not okay
})
(If you do care about FooError
conforming to ErrorConstructor
, that can be arranged, but it's a bit more annoying. Let me know if you'd like me to elaborate.)
Anyway, hope that helps; good luck!
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