TypeScript合并查询函数时联合类型访问length属性报错如何解决
问题原因
TypeScript 无法通过 multiple 变量的布尔值自动关联 result 的实际类型,哪怕逻辑上 multiple 为 true 时 result 一定是数组,TS 也不会默认建立这个关联,所以直接访问 result.length 会提示单个 HTMLElement 不存在 length 属性。
解决方案
- 方案1:用原生类型收窄逻辑修复(推荐,无额外语法负担)
用 TS 可识别的Array.isArray()方法判断result类型,同时可以顺便优化报错提示的准确性:
const getDataTest = ( container: HTMLElement, dataTest: string, multiple = false ) => { const queryMethod = multiple ? queryHelpers.queryAllByAttribute : queryHelpers.queryByAttribute; const result = queryMethod( 'data-test', container, dataTest ); // 用Array.isArray做类型收窄,TS会自动识别分支内的result类型 if ( (Array.isArray(result) && result.length === 0) || (!Array.isArray(result) && !result) ) { const errorMsg = Array.isArray(result) ? `Unable to find any elements by: [data-test="${dataTest}"]` : `Unable to find element by: [data-test="${dataTest}"]` throw queryHelpers.getElementError(errorMsg, container); } return result; };
- 方案2:添加函数重载,优化调用时的类型体验
如果希望调用函数时 TS 能自动根据multiple参数推断返回值类型,不用手动做类型断言,可以加上函数重载声明:
// 重载声明:multiple为false时返回单个元素 function getDataTest(container: HTMLElement, dataTest: string, multiple?: false): HTMLElement // 重载声明:multiple为true时返回元素数组 function getDataTest(container: HTMLElement, dataTest: string, multiple: true): HTMLElement[] // 原函数实现 function getDataTest( container: HTMLElement, dataTest: string, multiple = false ): HTMLElement | HTMLElement[] { // 这里的实现和方案1完全一致即可 const queryMethod = multiple ? queryHelpers.queryAllByAttribute : queryHelpers.queryByAttribute; const result = queryMethod( 'data-test', container, dataTest ); if ( (Array.isArray(result) && result.length === 0) || (!Array.isArray(result) && !result) ) { const errorMsg = Array.isArray(result) ? `Unable to find any elements by: [data-test="${dataTest}"]` : `Unable to find element by: [data-test="${dataTest}"]` throw queryHelpers.getElementError(errorMsg, container); } return result; }
调用示例:
// 自动推断返回类型为HTMLElement const btn = getDataTest(container, 'submit-btn') // 自动推断返回类型为HTMLElement[] const listItems = getDataTest(container, 'list-item', true)
- 临时方案:用类型断言绕开检查(不推荐,仅应急用)
如果只需要快速修复报错,不需要严格的类型校验,可以手动告诉TS当前result的类型:
if ((multiple && (result as HTMLElement[]).length === 0) || !result)
这种方式绕过了TS的类型校验,逻辑出错时无法提前发现,仅适合临时调试使用。
内容的提问来源于stack exchange,提问作者Dean James
相关产品推荐
相关产品推荐

