TypeScript中数组类型窄于查询类型时如何正确使用indexOf方法
错误原因
你遇到的类型报错是因为:NAVIGABLE_STATES 是三个可导航状态字面量组成的只读数组,其元素类型为 "show_instructions" | "lift_box" | "turn_box" 窄联合类型。而传入 indexOf 的参数 state 是更宽的 OverallState 类型,额外包含了不可导航的 "wait_for_connection"、"calibrate" 两种状态,TS 不允许将宽类型直接传入要求窄类型的入参,因此抛出错误:
Argument of type 'OverallState' is not assignable to parameter of type '"show_instructions" | "lift_box" | "turn_box"'.
Type '"wait_for_connection"' is not assignable to type '"show_instructions" | "lift_box" | "turn_box"'.
解决方案
方案1:添加类型守卫+运行时边界校验(推荐)
通过类型守卫先判断当前状态是否可导航,同时补充边界处理逻辑,避免运行时出现越界取到undefined的问题:
const NAVIGABLE_STATES = ["show_instructions", "lift_box", "turn_box"] as const; // 抽离可导航状态类型,方便复用 type NavigableState = typeof NAVIGABLE_STATES[number]; type OverallState = | "wait_for_connection" | "calibrate" | NavigableState; // 类型守卫:运行时判断状态是否属于可导航范围,同时收窄类型 function isNavigableState(state: OverallState): state is NavigableState { return (NAVIGABLE_STATES as readonly string[]).includes(state); } function navigate(state: OverallState, direction: -1 | 1): OverallState { // 不可导航状态直接返回原值 if (!isNavigableState(state)) return state; const currentIdx = NAVIGABLE_STATES.indexOf(state); const nextIdx = currentIdx + direction; // 越界处理:超出首尾时停在边界状态,可按需修改为循环跳转逻辑 if (nextIdx < 0) return NAVIGABLE_STATES[0]; if (nextIdx >= NAVIGABLE_STATES.length) return NAVIGABLE_STATES.at(-1)!; return NAVIGABLE_STATES[nextIdx]; }
方案2:直接类型断言(适合调用前已做入参校验的场景)
如果你的业务逻辑已经保证调用navigate时传入的一定是可导航状态,可以直接用类型断言绕过类型检查,同时建议补充越界判断避免运行时异常:
function navigate(state: OverallState, direction: -1 | 1): OverallState { const currentIdx = NAVIGABLE_STATES.indexOf(state as NavigableState); const nextIdx = currentIdx + direction; return nextIdx >= 0 && nextIdx < NAVIGABLE_STATES.length ? NAVIGABLE_STATES[nextIdx] : state; }
内容的提问来源于stack exchange,提问作者Neal Ehardt
相关产品推荐
相关产品推荐

