TypeScript中HTMLElement无法赋值给泛型T的报错如何解决
TypeScript泛型DOM查询函数默认参数类型报错修复
问题表现
封装泛型DOM查询函数时,给构造函数类型参数设置HTMLElement作为默认值抛出类型错误:
Type 'HTMLElement' is not assignable to type 'T'.
'HTMLElement' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Element'.
初始问题代码:
function get<T extends Element>( selector: string, type: new () => T = HTMLElement, // 该行报错 ): T { const elements = document.querySelectorAll(selector); if (elements.length === 1) { const element = elements.item(0); if (element instanceof type) { return element; } throw 'Wrong type'; } else if (elements.length === 0) { throw `No element was found: ${selector}`; } else { throw `Non-unique result: ${selector}`; } }
报错根因
泛型T是调用方可以自定义的类型参数,约束为Element的任意子类型(比如HTMLDivElement、HTMLCanvasElement等)。如果直接给type参数设置默认值HTMLElement,TypeScript无法保证这个默认构造函数能兼容所有可能的T子类型:如果调用方显式指定T为HTMLInputElement,默认的HTMLElement构造函数显然不满足new () => T的类型要求,因此触发类型校验错误。
修复代码
给泛型参数T设置默认类型为HTMLElement,同时对默认值做安全类型断言即可,修复后代码如下:
function get<T extends Element = HTMLElement>( selector: string, type: new () => T = HTMLElement as new () => T, ): T { const elements = document.querySelectorAll(selector); if (elements.length === 1) { const element = elements.item(0); if (element instanceof type) { return element; } throw 'Wrong type'; } else if (elements.length === 0) { throw `No element was found: ${selector}`; } else { throw `Non-unique result: ${selector}`; } }
用法说明
- 不传入第二个参数时,函数默认返回
HTMLElement类型,类型自动推导 - 需要查询特定类型元素时,同时传入对应DOM构造函数,返回值自动推导为对应元素类型,示例:
// 默认返回HTMLElement const container = get('#root'); // 返回HTMLInputElement类型 const usernameInput = get('#username', HTMLInputElement);
该类型断言是完全安全的:当调用方显式传入第二个构造函数参数时,默认值HTMLElement不会生效;仅在使用默认参数时断言才起作用,此时泛型T的默认值就是HTMLElement,不存在类型不匹配问题。
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

