假设
Event
和 GlobalEventHandlersEventMap
的基本/内置声明如下所示:
// lib.dom.d.ts
interface Event {
/**
* Returns the type of event, e.g. "click", "hashchange", or "submit".
*/
readonly type: string; // <-- note this part
}
interface GlobalEventHandlersEventMap {
click: MouseEvent;
//... all sorts of other built in events...
}
注意:在我的应用程序的上下文中,我知道
type
将始终是内置事件类型(GlobalEventHandlersEventMap
的键)或自定义事件类型(可以通过声明合并添加 -如下例所示)。
在其他地方的一些代码中,我有类似这样的内容:
class EventTriggered {
constructor(
readonly eventName: keyof GlobalEventHandlersEventMap
) {}
}
我想像这样构建一个实例:
const et = new EventTriggered(event.type);
这会导致错误,因为 eventName 应该是上述映射的键,但它收到的是一个字符串(因为
Event.type
是这样声明的)。
通过减速合并,我可以“注册”或“添加”自定义事件,如下所示:
// global.d.ts
interface GlobalEventHandlersEventMap {
myEvent: CustomEvent; // <--- this will be added to the original "list"
} // of events from above, thanks to generics
但是,如果我尝试同样的方法来“覆盖”
type
属性,它将不起作用......大概是因为它只是作为属性的变体添加。
// global.d.ts
interface Event {
readonly type: keyof GlobalEventHandlersEventMap;
}
接下来发生的事情是之前的错误仍然出现,但现在我的 IDE 显示
type
有两个声明:
我也看到了这个问题,但感觉不同 - 一方面,我没有得到与那个相同的错误:TypeScript声明合并 - 更改属性类型
好吧,我个人认为声明合并不是一个功能,而是一个错误:)
如果我理解正确,你想要一个联合类型,该联合类型将从
EventMap
的键名称中获取,但有时可能会有一些其他字符串不属于键名称联合的一部分。
可以更换
readonly eventName: keyof GlobalEventHandlersEventMap
与
readonly eventName: string
但是这种方法会让您丢失所有关键名称信息。 您可以使用打字稿的一些小技巧,如下所示。
readonly eventName: keyof GlobalEventHandlersEventMap | ({} & string)
这样 eventName 将是键名或任何其他字符串。自动完成也适用于此变量。