我正在尝试将我的项目从javascript迁移到打字稿,并且在处理事件的类移植方面遇到问题。
为了避免重复描述添加/删除事件侦听器的选项,我们使用如下包装器:
constructor() {
this.windowResizeHandler = new MyEventHandler(
target: window,
event: 'resize',
handler: e => this.handleResize_(e),
options: {passive: true, capturing: true},
);
}
connectedCallback() {
this.windowResizeHandler.add();
}
disconnectedCallback() {
this.windowResizeHandler.remove();
}
现在,在不丢失有关事件键入的信息的情况下,我不知道如何在打字稿中编写此内容。例如:
document.createElement('button').addEventListener('click', e => {
// Here e is MouseEvent.
});
但是如果我像这样写包装器:
interface EventHandlerParams {
readonly target: EventTarget;
readonly event: Event;
readonly listener: (e: Event) => void;
readonly params: AddEventListenerOptions;
}
export class EventHandler {
public constructor(params: EventHandlerParams) {}
}
然后我松散输入:
new MyEventHandler(
target: document.createElement('button'),
event: 'click',
handler: e => { /* Here e is just Event not MouseEvent */ },
options: {passive: true, capturing: true},
);
我在这里是否可以使用lib.dom.d.ts
中的事件类型?
答案 0 :(得分:1)
lib.dom.ts
中有一个类型,其中包含所有事件名称和事件参数类型之间的映射。它称为WindowEventMap
。
因此我们可以例如编写以下内容:
interface EventHandlerParams<T extends keyof WindowEventMap> {
readonly target: EventTarget;
readonly event: T;
readonly options: AddEventListenerOptions;
readonly listener: (e: WindowEventMap[T]) => void
}
export class EventHandler<T extends keyof WindowEventMap> {
public constructor(params: EventHandlerParams<T>) { }
}
new EventHandler({
target: document.createElement('button'),
event: 'click',
options: { passive: true },
listener: e => { e.x /* e is MouseEvent */ }
});
EventHandlerParams
现在是通用的,它将捕获事件名称作为类型参数T
。我们还使EventHandler
通用,并且T
取决于传递给它的婴儿车。有了T
(它将包含事件的字符串文字类型),我们可以从WindowEventMap
访问事件的实际参数类型并将其用于我们的侦听器签名中。
注意,我认为3.0之前的版本可能不会将侦听器的参数推断为正确的类型(它们可能会推断为any
)。如果您遇到此问题,请告诉我,我可以提供3.0之前的版本。
答案 1 :(得分:0)
@ titian-cernicova-dragomir我想要这样的东西(不起作用):
interface Mapping {
[Window]: WindowEventMap;
[HTMLElement]: HTMLElementEventMap;
}
interface EventHandlerParams<TTarget extends keyof Mapping,
TEventName extends keyof Mapping[TTarget],
TEvent extends Mapping[TTarget][TEventName]> {
readonly event: TEventName;
readonly listener: (event: TEvent) => void;
readonly params?: AddEventListenerOptions;
readonly target: TTarget;
}
export class EventHandler<TTarget extends keyof Mapping,
TEventName extends keyof Mapping[TTarget],
TEvent extends Mapping[TTarget][TEventName]> {
public constructor(params: EventHandlerParams<TTarget, TEventName, TEvent>) {}
}
但是不能使用它,因为类型不能是接口属性,并且没有任何其他选项可以为TTarget
提供约束。