搜索词
- dom.d.ts
- eventmap
建议
创建一个"Map",将 HTMLElement
与其相关的 EventMap
类型配对。
我们可以从 HTMLElement
推导出一个 tagName
,反之亦然,从 HTMLElementTagNameMap
类型中可以推导出。
type GetHTMLElementByTagName<
K extends keyof HTMLElementTagNameMap
> = HTMLElementTagNameMap[K];
type GetTagNameByHTMLElement<
E extends HTMLElementTagNameMap[keyof HTMLElementTagNameMap]
> = {
[P in keyof HTMLElementTagNameMap]: HTMLElementTagNameMap[P] extends E
? P
: never;
}[keyof HTMLElementTagNameMap];
但是,目前在 Typescript 的类型系统中,没有方法可以从 dom.d.ts
中的现有类型推断出元素的事件Map。
interface HTMLElement extends ... {
// ...
// how to extract type HTMLElementEventMap from keyof HTMLElementEventMap?
addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
// ...
用例
创建我们自己的 [element].(add|remove)EventListener()
版本会很好。对于拖放库 sortablejs
,我们暴露了一个基于浏览器分配捕获值的辅助函数 [element].(add|remove)EventListener()
。
function off(el, event, fn) {
el.removeEventListener(event, fn, captureMode());
}
不幸的是,我无法从具有泛型的元素 el
中推断出 event
和 fn
函数参数。
示例
所有其他 "Map" 实现都是使用接口的 string <-> Type
对,而我们需要的是 Type <-> Type
对。
以下是我目前想到的笨拙解决方法。我猜很多其他用户也会想要这个,这就是为什么我创建了这个问题。
检查清单
我的建议满足以下指导原则:
- 这不会对现有的 TypeScript/JavaScript 代码造成破坏性更改
- 这不会改变现有 JavaScript 代码的运行时行为
- 这可以在不根据表达式的类型发出不同的 JS 的情况下实现
- 这不是一个运行时特性(例如库功能、带有 JavaScript 输出的非 ECMAScript 语法等)
- 这个特性将与 TypeScript's Design Goals 的其他部分保持一致。
边注
- 这是个破坏性的更改,但不确定如何优雅地处理,因为 Typescript 没有遵循语义版本规范。
- 在
HTMLElement
上有一些缺失的事件,如pointermove
。这些应该更新。除非得到建议,否则我会发布一个新的问题。 - 使用自定义元素和自定义事件的用户需要一种插入他们自己的
Element <-> EventMap
对的方法。这可能通过将它们的类型附加到全局命名空间来完成。
4条答案
按热度按时间bxfogqkk1#
我找到了这个:https://stackoverflow.com/a/62010854/3871776
i2byvkas2#
@std4453 相关但无法从类型推断事件Map的问题。
uyhoqukh3#
How about this? (most of inspiration from @std4453's shared thing.)
playground
kulphzqa4#
我认为这次讨论的目标不应该只是"让我们探索解决方法",而更应该朝着"让我们将这个功能添加到Typescript或类型本身中"的方向发展。我们已经有了解决方法。