# 模块

¥Models

警告

createModel(...) 函数已弃用,并将在 XState 版本 5 中删除。建议使用 类型基因 (opens new window) 代替。

¥The createModel(...) function is deprecated and will be removed in XState version 5. It is recommended to use Typegen (opens new window) instead.

在 XState 中,你可以使用 createModel(...) 在外部对机器的 contextevents 进行建模。这提供了一种强类型 contextevents 的便捷方法,以及将来事件创建、分配和其他实现细节的辅助程序。

¥In XState, you can model a machine's context and events externally by using createModel(...). This provides a convenient way to strongly type context and events, as well as helpers for event creation, assignment and other implementation details in the future.

使用 createModel(...) 是完全可选的,旨在改善开发者体验。使用它的主要原因是:

¥Using createModel(...) is completely optional, and is meant to improve the developer experience. The main reasons for using it are:

  • 以强类型的方式分离和组织 contextevents

    ¥Separating and organizing context and events in a strongly-typed way

  • 防止 assign(...) 出现打字问题

    ¥Preventing typing issues with assign(...)

  • 指定事件创建者以更轻松、更安全地创建事件

    ¥Specifying event creators for easier and safer event creation

  • 可能与其他机器共享模型

    ¥Potentially sharing the model with other machines

  • 未来的开发者体验改进,例如指定操作、防护等。

    ¥Future developer experience improvements, such as specifying actions, guards, etc.

# createModel(...)

createModel(...) 函数需要

¥The createModel(...) function takes

争论 类型 描述
initialContext object 初始 context
creators(可选) object 包含各种事件创建者的对象

creators 对象包括以下属性:

¥The creators object includes the following properties:

争论 类型 描述
events object 包含事件创建者的对象

creators.events 对象的键是事件类型,值是接受任意数量的参数并返回事件负载的函数。

¥The keys of the creators.events object are event types, and the values are functions that accept any number of arguments and return the event payload.

# 建模环境

¥Modeling context

由于模型定义了机器的 context,因此可以在机器定义中使用该模型,将其初始 context 设置为 model.initialContext,并使用 model.assign 更新机器的 context

¥Since the model defines the machine's context, the model can be used within the machine definition to set its initial context with model.initialContext and to update the machine's context with model.assign.

model.assign 功能是按照模型 context 的形状设计的,使其成为 assign 动作的方便且类型安全的替代品。

¥The model.assign function is typed to the shape of the model's context, making it a convenient and type-safe replacement for the assign action.

import { createModel } from 'xstate/lib/model';

const userModel = createModel({
  name: 'Someone',
  age: 0
});

// ...

const machine = userModel.createMachine({
  context: userModel.initialContext,
  // ...
  entry: userModel.assign({ name: '' })
});

# 建模事件

¥Modeling events

在模型中对机器事件进行建模有两个好处:

¥Modeling machine events in a model gives two benefits:

  • 可以通过调用 model.events.eventName(...) 创建事件

    ¥Events can be created by calling model.events.eventName(...)

  • 向机器定义提供类型信息,为操作定义提供特定于事件的类型安全性

    ¥Provides type information to the machine definition, providing event-specific type safety for action definitions

import { createModel } from 'xstate/lib/model';

const userModel = createModel(
  // Initial context
  {
    name: 'David',
    age: 30
  },
  {
    // Event creators
    events: {
      updateName: (value) => ({ value }),
      updateAge: (value) => ({ value }),
      anotherEvent: () => ({}) // no payload
    }
  }
);

const machine = userModel.createMachine(
  {
    context: userModel.initialContext,
    initial: 'active',
    states: {
      active: {
        on: {
          updateName: {
            actions: userModel.assign({
              name: (_, event) => event.value
            })
          },
          updateAge: {
            actions: 'assignAge'
          }
        }
      }
    }
  },
  {
    actions: {
      assignAge: userModel.assign({
        age: (_, event) => event.value
      })
    }
  }
);

// This sends the following event:
// {
//   type: 'updateName',
//   value: 'David'
// }
const nextState = machine.transition(
  undefined,
  userModel.events.updateName('David')
);

# TypeScript

createModel(...) 函数推断以下类型:

¥The createModel(...) function infers the following types:

  • context 是从 createModel(initialContext, creators) 中的第一个参数推断出来的

    ¥context is inferred from the first argument in createModel(initialContext, creators)

  • events 是从 createModel(initialContext, creators) 中的 creators.events 推断出来的

    ¥events is inferred from creators.events in createModel(initialContext, creators)

import { createModel } from 'xstate/lib/model';

const userModel = createModel(
  {
    name: 'David', // inferred as `string`
    age: 30, // inferred as `number`
    friends: [] as string[] // explicit type
  },
  {
    events: {
      updateName: (value: string) => ({ value }),
      updateAge: (value: number) => ({ value }),
      anotherEvent: () => ({}) // no payload
    }
  }
);

// Context inferred as:
// {
//   name: string;
//   age: number;
//   friends: string[];
// }

// Events inferred as:
// | { type: 'updateName'; value: string; }
// | { type: 'updateAge'; value: number; }
// | { type: 'anotherEvent'; }

# 从模型创建机器

¥Creating a machine from a model

应使用 model.createMachine(...) 方法,而不是将 contextevent 的类型显式指定为 createMachine<TContext, TEvent>(...) 中的类型参数:

¥Instead of specifying the type of context and event explicitly as type parameters in createMachine<TContext, TEvent>(...), the model.createMachine(...) method should be used:

















const machine = userModel.createMachine({
  context: userModel.initialContext,
  initial: 'active',
  states: {
    active: {
      on: {
        updateName: {
          actions: userModel.assign({
            name: (_, event) => event.value // inferred
          })
        }
      }
    }
  }
});

# 缩小分配事件类型

¥Narrowing assign event types

options.actions 中引用 assign() 操作时,你可以在 model.assign(assignments, eventType) 的第二个参数中缩小该操作接受的事件类型:

¥When an assign() action is referenced in options.actions, you can narrow the event type that the action accepts in the 2nd argument of model.assign(assignments, eventType):

const assignAge = userModel.assign(
  {
    // The `event.type` here is restricted to "updateAge"
    age: (_, event) => event.value // inferred as `number`
  },
  'updateAge' // Restricts the `event` allowed by the "assignAge" action
);

const machine = userModel.createMachine({
  context: userModel.initialContext,
  initial: 'active',
  states: {
    active: {
      on: {
        updateAge: {
          actions: assignAge
        }
      }
    }
  }
});

警告

具有缩小事件类型的分配操作不能放置在 createMachine(configuration, options) 中计算机选项的 actions: {...} 属性内。这是因为应假定 options.actions 中的操作可能接收任何事件,即使机器配置另有建议。

¥Assign actions with narrowed event types cannot be placed inside the actions: {...} property of machine options in createMachine(configuration, options). This is because actions in options.actions should be assumed to potentially receive any event, even if the machine configuration suggests otherwise.

# 从模型中提取类型

¥Extracting types from model

自 4.22.1 起

¥Since 4.22.1

你可以使用 ContextFrom<T>EventFrom<T> 类型从模型中提取 contextevent 类型:

¥You can extract context and event types from a model using the ContextFrom<T> and EventFrom<T> types:

 













 
 

import { ContextFrom, EventFrom } from 'xstate';
import { createModel } from 'xstate/lib/model';

const someModel = createModel(
  {
    /* ... */
  },
  {
    events: {
      /* ... */
    }
  }
);

type SomeContext = ContextFrom<typeof someModel>;
type SomeEvent = EventFrom<typeof someModel>;