You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 01:04:07