TypeScript访问number|number[]类型数组时索引访问报错问题
TypeScript联合类型窄化问题:直接访问数组元素报错,存入变量后正常
当处理类型为number[] | number的数组元素时,会遇到一个奇怪的现象:明明用Array.isArray()检查确认了当前元素是数组类型,但直接访问它的子数组索引时TypeScript还是会报错;可如果把这个元素先存入一个变量,再访问索引就完全正常。
问题代码示例
const minuteRange = [1, 2, 3, 4, [7, 9], [11, 13]]; const minRange = minuteRange; // const lastEl: number[] | number = minRange[minRange.length - 1] ?? 0; // 若将minRange[minRange.length - 1]替换为上方定义的lastEl则可正常运行 const lastMinuteRangeNum = Array.isArray(minRange[minRange.length - 1]) ? minRange[minRange.length - 1][1] : minRange[minRange.length - 1] ?? 0;
原因分析
TypeScript的类型窄化逻辑只针对变量生效,而不是动态表达式。你直接写minRange[minRange.length - 1]是一个动态计算的表达式,编译器没办法保证两次调用这个表达式时返回的值类型完全一致——虽然运行时肯定是同一个值,但编译器不会做这个假设。
当你把表达式结果存入变量lastEl后,TypeScript可以通过Array.isArray()的检查,把变量的类型精准窄化为number[],后续访问索引自然就符合类型要求了。
解决方法
方法一:存入变量后处理(推荐)
把目标元素先存入变量,再进行类型检查和索引访问:
const minuteRange = [1, 2, 3, 4, [7, 9], [11, 13]]; const minRange = minuteRange; const lastEl = minRange[minRange.length - 1] ?? 0; const lastMinuteRangeNum = Array.isArray(lastEl) ? lastEl[1] : lastEl;
方法二:使用类型断言(谨慎使用)
如果你能100%确认当前表达式的类型,可以用类型断言强制告诉编译器类型:
const minuteRange = [1, 2, 3, 4, [7, 9], [11, 13]]; const minRange = minuteRange; const lastMinuteRangeNum = Array.isArray(minRange[minRange.length - 1]) ? (minRange[minRange.length - 1] as number[])[1] : minRange[minRange.length - 1] ?? 0;
内容的提问来源于stack exchange,提问作者Instance Of Code
相关产品推荐
相关产品推荐

