如何使用TypeScript Map和错误处理程序?

时间:2017-09-26 12:30:14

标签: typescript

为什么TypeScript会抱怨这段代码?

class FooError extends Error {
}

const map = new Map<ErrorConstructor, any> ([
  [Error, 'do this'],
  [FooError, 'do that']
])
  

类型'typeof FooError'不能分配给'ErrorConstructor'类型。

1 个答案:

答案 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原型,这很好,因为FooErrorError的子类型。它是一个构造函数,它接受一个参数,因为它推迟到超类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;我希望我详细说明。)

无论如何,希望有所帮助;祝你好运!