能否用JSDoc实现document.getElementById的泛型类型守卫函数?
用JSDoc实现泛型元素获取的类型守卫
问题背景
想要把以下元素校验逻辑通用化:
const element = document.getElementById('foo') if (!element || !(element instanceof HTMLInputElement)) throw new Error('Failed to locate HTML element with id foo and type HTMLInputElement!') // now we're safe, element is not null and it has the expected type
在TypeScript中可以通过泛型函数实现该逻辑:
type Class<T> = new (...args: any[]) => T function getElement<T extends HTMLElement>(id: string, type: Class<T>): T { const element = document.getElementById(id) if (!element || !(element instanceof type)) throw new Error(`Failed to locate HTML element with id ${id} and type ${type}!`) return element }
但在纯JavaScript中,尝试用JSDoc定义泛型Class类型时遇到两个IDE错误:
element instanceof type报错:“'instanceof'表达式的右侧必须是'any'类型、类、函数、可赋值给'Function'接口的类型,或带有'Symbol.hasInstance'方法的对象类型。ts(2359)”return element报错:“类型'HTMLElement'无法赋值给类型'T'。'T'可被实例化为与'HTMLElement'无关的任意类型。ts(2322)”
请问能否用JSDoc实现该泛型类型守卫功能?
解决方案
可以通过JSDoc的泛型语法和类型断言解决这两个问题,正确的实现代码如下:
/** * @template {HTMLElement} T * @param {string} id * @param {new (...args: any[]) => T} type * @returns {T} */ function getElement(id, type) { const element = document.getElementById(id); if (!element || !(element instanceof type)) { throw new Error(`Failed to locate HTML element with id ${id} and type ${type.name}!`); } return /** @type {T} */ (element); }
错误修复说明:
instanceof报错解决:问题源于JSDoc对type参数的类型定义模糊,通过@param {new (...args: any[]) => T} type明确标记它是可构造出T类型实例的构造函数,TypeScript就能识别instanceof的合法性。- 返回值类型不匹配解决:虽然通过
instanceof完成了运行时校验,但TypeScript的静态类型推断无法自动将HTMLElement缩小到具体的T类型,因此需要用/** @type {T} */做类型断言,明确告知编辑器返回值的具体类型。
使用示例:
// 调用时编辑器会自动推断返回类型为HTMLInputElement const input = getElement('foo', HTMLInputElement); input.value = 'test'; // 类型安全,无报错
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

