为什么TypeScript会抱怨这段代码?
class FooError extends Error {
}
const map = new Map<ErrorConstructor, any> ([
[Error, 'do this'],
[FooError, 'do that']
])
类型'typeof FooError'不能分配给'ErrorConstructor'类型。
答案 0 :(得分:4)
好吧,让我们看一下ErrorConstructor
的定义:
interface ErrorConstructor {
new(message?: string): Error; // is a constructor
(message?: string): Error; // is callable
readonly prototype: Error; // has an Error prototype
}
因此,ErrorConstructor
需要是一个带有可选字符串参数的构造函数,并且它还需要作为函数调用,并且它需要有一个Error
原型。让我们来看看你的FooError
课程:
class FooError extends Error {
}
FooError.prototype; // okay, type FooError
new FooError("okay"); // okay
FooError("oops"); // error
它有一个FooError
原型,这很好,因为FooError
是Error
的子类型。它是一个构造函数,它接受一个参数,因为它推迟到超类Error
,它是一个ErrorConstructor
。但它不能作为函数调用。因此FooError
不是ErrorConstructor
。
此时,您需要确定您是否真的关心它是ErrorConstructor
。您打算将其称为FooError('msg')
而不是new FooError('msg')
吗?我对此表示怀疑。就此而言,您是否关心构造函数prototype
的类型为FooError
?可能不是。在这种情况下,请勿使用ErrorConstructor
。相反,使用以下接口,它只关心是一个可选的one-string-arg构造函数:
interface NoFrillsErrorConstructor {
new(message?: string): Error;
}
现在您的代码将起作用:
const map = new Map<NoFrillsErrorConstructor, any> ([
[Error, 'do this'],
[FooError, 'do that']
])
只要您只使用地图的键作为构造函数,一切都会好的:
map.forEach((val, err) => {
err.prototype; // exists, but is type any. Who cares, right?
new err(); // okay
err(); // not okay
})
(如果你 关心符合FooError
的{{1}},那可以安排,但它更烦人。如果你和我告诉我# 39;我希望我详细说明。)
无论如何,希望有所帮助;祝你好运!