XState TypeScript开发中invoke.onDone.actions类型不兼容报错
问题根因
这个类型错误是拆分定义状态节点时的常见TypeScript推导失效问题:你把questions/search等状态配置定义在createMachine外部时,TypeScript无法自动关联这些配置对应的上下文类型,导致assign()被推导为AssignAction<unknown, any>,和onDone转换要求的动作类型不匹配。
报错中提到的「缺少数组属性length/pop/push」是类型不匹配后的连锁提示,不是要求你把actions改成数组格式。
修复方案
选任意一种即可解决:
方案1:给assign显式传泛型(改动最小)
直接给assign指定上下文和invoke完成事件的类型,绕开自动推导失效问题:
import { assign, DoneInvokeEvent } from 'xstate'; // 对应修改onDone配置段 onDone: { target: 'asking', actions: assign<EventsSearchContext, DoneInvokeEvent<Question[]>>({ questions: (_, event) => event.data }) }
这里DoneInvokeEvent的泛型传入fetchQuestions返回的结果类型Question[],还能获得完整的event.data类型提示,不需要写event: any。
方案2:给拆分的状态配置加类型标注
如果要保留多文件拆分状态的代码结构,可以在定义独立状态时就标注对应类型,让TS提前感知上下文类型,后续不需要在每个assign上重复写泛型:
import type { StateNodeConfig } from 'xstate'; // 导出questions状态时直接标注匹配的上下文、事件类型 export const questions: StateNodeConfig<EventsSearchContext, any> = { initial: 'loading', states: { loading: { invoke: { id: 'loadQuestions', src: fetchQuestions, onDone: { target: 'asking', actions: assign({ questions: (_, event) => event.data }) }, onError: {} }, tags: ['loading'], }, asking: { always: [{ target: '#search', cond: 'questionsExhausted' }], on: { QUESTION_ANSWERED: {} } } } }
额外注意点
你现有代码还有两个潜在问题,建议同步修复:
src: (context, event) => fetchQuestions写法错误:invoke的src需要返回Promise/状态机/可观察对象,你当前写法是把fetchQuestions函数本身作为返回值,invoke执行时拿不到异步结果,直接写src: fetchQuestions即可QUESTION_ANSWERED: ''空字符串不是XState支持的合法target值,无状态跳转需求时配置为空对象即可
内容的提问来源于stack exchange,提问作者serlingpa
相关产品推荐
相关产品推荐

