如何为TypeScript包装函数声明基于参数的条件返回类型?
为包装函数
createElem 编写正确的TypeScript类型声明 TypeScript 能够根据传入的字符串参数,自动推断 globalThis.document.createElement('img') 的返回类型为 HTMLImageElement。但自行编写的包装函数 createElem 目前返回所有元素类型的联合类型,无法根据传入的 tag 参数精准推断对应返回类型,需要调整类型声明让它和原生API具备相同的类型推断能力。
原生API示例
const elem1 = globalThis.document.createElement('img'); // 类型:HTMLImageElement console.log(elem1.constructor.name); // 'HTMLImageElement'
待修正的包装函数
const createElem = (tag: keyof HTMLElementTagNameMap) => { const elem = globalThis.document.createElement(tag); elem.dataset.created = String(Date.now()); return elem; }; const elem2 = createElem('img'); // 类型:HTMLElement | ...68 more... console.log(elem2.constructor.name); // 'HTMLImageElement'
解决方案:使用泛型绑定键值映射
我们可以通过泛型将传入的 tag 参数和对应的元素类型做绑定,利用TypeScript内置的 HTMLElementTagNameMap 接口(它定义了HTML标签名到对应元素类型的映射关系)实现精准类型推断。
修正后的代码如下:
const createElem = <T extends keyof HTMLElementTagNameMap>(tag: T): HTMLElementTagNameMap[T] => { const elem = globalThis.document.createElement(tag); elem.dataset.created = String(Date.now()); return elem; }; // 现在类型推断正常工作 const elem2 = createElem('img'); // 类型:HTMLImageElement const elem3 = createElem('p'); // 类型:HTMLParagraphElement
原理说明
- 泛型
T被约束为keyof HTMLElementTagNameMap,确保传入的tag是合法的HTML标签名; - 返回类型指定为
HTMLElementTagNameMap[T],让TypeScript根据传入的具体tag(即泛型T的实际值),从映射表中取出对应的元素类型,实现和原生createElement一致的类型推断效果。
内容的提问来源于stack exchange,提问作者Pilaf T. Pilafian
相关产品推荐
相关产品推荐

