TypeScript中Plan类型parsePlan函数返回值类型报错问题
报错原因
TypeScript 对带剩余元素的元组类型的索引访问推导存在静态局限:
- 你定义的
Plan<T> = [T[], ...T[]]仅能明确标记索引0的类型为T[],其余位置为T,但当你用类型为number的入参index去访问plan[index]时,TS无法通过静态代码分析证明你运行时不会取到索引0的值——哪怕你已经写了index < 1时抛错的守卫,也没法让TS把「index < plan.length分支下的index一定不等于0」这个逻辑关联起来,毕竟plan.length是运行时动态值,TS不会做跨表达式的复杂类型收窄。 - 因此TS会把
plan[index]的类型推导为所有可能索引值对应类型的联合,也就是T | T[],和你声明的返回值T不匹配,就抛出了类型错误。
修复方法
推荐用解构的写法重写函数逻辑,完全规避类型断言,让TS自动推导正确类型,逻辑和原实现完全等价:
type Plan<T> = [T[], ...T[]]; function parsePlan<T>(plan: Plan<T>, index: number): T { if (index < 1) throw new Error("Invalid index"); // 解构拆分重复项数组和初始阶段项数组,TS能直接推导两者的明确类型 const [repeatItems, ...initialItems] = plan; const initialCount = initialItems.length; return index - 1 < initialCount ? initialItems[index - 1] : repeatItems[(index - 1 - initialCount) % repeatItems.length]; } // 测试用例可正常通过类型校验 const life: Plan<string> = [ ["getUp", "work", "sleep"], "birth", "grow" ]; console.log(parsePlan(life, 1)); // "birth" console.log(parsePlan(life, 2)); // "grow" console.log(parsePlan(life, 3)); // "getUp" console.log(parsePlan(life, 4)); // "work"
如果不想调整原有逻辑结构,也可以给非0索引的访问加明确的类型断言,告诉TS此处访问的值一定是T类型,代码改动量最小:
function parsePlan<T>(plan: Plan<T>, index: number): T { if(index < 1) throw new Error("Invalid index"); return index < plan.length ? plan[index] as T : plan[0][(index-plan.length)%(plan[0].length)] }
内容的提问来源于stack exchange,提问作者dbld
相关产品推荐
相关产品推荐

