You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

XState(v5)类型化Action与Event类型冲突的TypeScript问题

解决XState v5 + TypeScript中Action的事件类型匹配问题

方法1:给Action显式指定事件与参数类型

在定义可复用Action时,通过TypeScript泛型明确指定该Action接收的特定事件类型参数类型,让TypeScript正确识别事件属性:

import { setup, createActor } from 'xstate';

// 提取事件类型复用
type ExampleEvents = 
  | { type: 'eventWithNoParams' }
  | { type: 'eventWithParams', meta: string };

// 从联合类型中筛选出目标事件类型
type EventWithParams = Extract<ExampleEvents, { type: 'eventWithParams' }>;

const exampleMachine = setup({
  types: {
    events: {} as ExampleEvents
  },
  actions: {
    // 显式声明上下文、事件、参数的类型
    doSomething: ({ event }: { context: {}; event: EventWithParams }, params?: string) => {
      event.meta; // 类型校验通过,无报错
      params; // 参数类型已指定为string,不再是unknown
    }
  }
}).createMachine({
  id: 'example',
  initial: 'start',
  states: {
    start: {
      on: {
        'eventWithNoParams': 'nextState'
      }
    },
    nextState: {
      on: {
        'eventWithParams': {
          target: 'finalState', // 修正原代码跳转目标错误
          actions: 'doSomething'
        }
      }
    },
    finalState: {
      type: 'final'
    }
  }
});

const actor = createActor(exampleMachine);
actor.start();
actor.send({ type: 'eventWithNoParams' });
actor.send({ type: 'eventWithParams', meta: 'someData' });

方法2:使用内联Action(单次场景更简洁)

如果Action仅在特定事件的转换中使用,直接在转换逻辑里定义内联Action,TypeScript会自动推断当前事件的类型:

import { setup, createActor } from 'xstate';

type ExampleEvents = 
  | { type: 'eventWithNoParams' }
  | { type: 'eventWithParams', meta: string };

const exampleMachine = setup({
  types: {
    events: {} as ExampleEvents
  }
}).createMachine({
  id: 'example',
  initial: 'start',
  states: {
    start: {
      on: {
        'eventWithNoParams': 'nextState'
      }
    },
    nextState: {
      on: {
        'eventWithParams': {
          target: 'finalState',
          // 内联Action自动匹配当前事件类型
          actions: ({ event }) => {
            event.meta; // 类型校验正常
          }
        }
      }
    },
    finalState: {
      type: 'final'
    }
  }
});

const actor = createActor(exampleMachine);
actor.start();
actor.send({ type: 'eventWithNoParams' });
actor.send({ type: 'eventWithParams', meta: 'someData' });

关键提示

  • Extract<EventType, { type: 'TargetEvent' }>是TypeScript内置工具类型,专门用于从联合类型中筛选出指定类型,完美适配XState的事件联合场景。
  • 可复用Action优先用方法1做类型声明;单次使用的Action用方法2更高效。
  • 原代码中eventWithParams的跳转目标存在错误,已修正为finalState,避免状态循环。

内容的提问来源于stack exchange,提问作者Tom Parke

火山引擎 最新活动