泛型参数扩展类型,但处于逆变位置,typescript可以';我不能统一它
我试图允许我的函数使用者使用更宽的类型,但我在反变位置和类型脚本中使用这种类型 简化代码:泛型参数扩展类型,但处于逆变位置,typescript可以';我不能统一它,typescript,Typescript,我试图允许我的函数使用者使用更宽的类型,但我在反变位置和类型脚本中使用这种类型 简化代码: function wrapper<T extends Event = Event>(node: HTMLElement) { const handler = (e: T) => console.log(e.cancelable); node.addEventListener("click", handler); } 我如何表达我的意图以便typesc
function wrapper<T extends Event = Event>(node: HTMLElement) {
const handler = (e: T) => console.log(e.cancelable);
node.addEventListener("click", handler);
}
我如何表达我的意图以便typescript理解我
完整代码:
export function tracker(
eventType: string,
options?: boolean | AddEventListenerOptions
) {
const stream: Stream<Event> = Stream.empty();
function tracker(node: HTMLElement) {
const handler = (event: Event) => stream.shamefullySendNext(event);
node.addEventListener( eventType, handler, options);
return {
destroy: () => {
node.removeEventListener(eventType, handler);
stream.shamefullySendComplete();
},
};
}
return {
stream,
tracker,
};
}
导出函数跟踪器(
eventType:string,
选项?:布尔| AddEventListenerOptions
) {
const stream:stream=stream.empty();
函数跟踪器(节点:HtmleElement){
const handler=(事件:event)=>stream.shamefullySendNext(事件);
addEventListener(事件类型、处理程序、选项);
返回{
销毁:()=>{
removeEventListener(事件类型,处理程序);
stream.shamefullySendComplete();
},
};
}
返回{
流动
追踪器,
};
}
您的问题相当令人困惑,但我相信您想要的是根据事件类型(即“单击”)而不是事件进行优化
我们永远不能安全地使用一个扩展事件的泛型T
,因为这个T
可以有任意的附加属性。考虑下面的例子:
interface MyEvent extends Event {
customProperty: string
};
const handler = (e: MyEvent) => console.log(e.cancelable);
任何事件侦听器都无法执行回调处理程序
,因为它们的事件
缺少属性自定义属性
。这就是为什么会出现“Type'Event'不可分配给Type'T”的错误
但是,我们可以细化事件类型,因为这是addEventListener
所做的
addEventListener<K extends keyof HTMLElementEventMap>(
type: K,
listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any,
options?: boolean | AddEventListenerOptions
): void;
addEventListener(
type: string,
listener: EventListenerOrEventListenerObject,
options?: boolean | AddEventListenerOptions
): void;
我不明白你为什么要使用泛型,或者你的真正意图是什么。是否可以使用
函数包装器(node:HTMLElement){const handler=(e:Event)=>console.log(e.cancelable);node.addEventListener(“click”,handler);}
,如图所示?如果没有,请详细说明到底出了什么问题。在实际代码中,有一个函数取代了console.log,将e推到用户土地上。用户可以定义泛型,并保证该值为特定类型。我在问题中添加了完整的代码。当您创建一个接受T extends Event
的函数时,您会遇到这个错误,因为T
可能类似于接口MyEvent extends Event{customProperty:string}代码>是事件侦听器永远无法实现的。您可以将其设置为事件类型的泛型(K extensed keyof HTMLElementEventMap
),而不是event
,我们可以将其传递给addEventListener
,它是事件类型的泛型,但事件类型始终是“click”
?你可以将泛型添加到你的跟踪器
中,但实际上我没有得到任何错误,除了不知道从哪里导入流
(因为你有事件
而不是特定事件)。这是你想要的吗?在陈述了我的问题并阅读了你的回答后,我意识到我的整个前提是错误的。谢谢我仍然想知道是否可以让用户以某种方式断言事件类型。我在考虑这样一个场景,其中有人正在侦听某个web组件事件,它使用CustomEvent
的某个子类调用处理程序。我担心typescript无法知道CustomEvent
子类和事件名称之间的关系。。。
addEventListener<K extends keyof HTMLElementEventMap>(
type: K,
listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any,
options?: boolean | AddEventListenerOptions
): void;
addEventListener(
type: string,
listener: EventListenerOrEventListenerObject,
options?: boolean | AddEventListenerOptions
): void;
export function tracker<K extends keyof HTMLElementEventMap>(
eventType: K,
options?: boolean | AddEventListenerOptions
) {
const stream: Stream<HTMLElementEventMap[K]> = Stream.empty();
function tracker(node: HTMLElement) {
const handler = (event: HTMLElementEventMap[K]) => stream.shamefullySendNext(event);
node.addEventListener<K>( eventType, handler, options);
return {
destroy: () => {
node.removeEventListener(eventType, handler);
stream.shamefullySendComplete();
},
};
}
return {
stream,
tracker,
};
}