fetchMachine中服务的正确类型(xstate、typescript)

ff29svar  于 2022-12-19  发布在  TypeScript
关注(0)|答案(1)|浏览(151)

我开始尝试使用xstate,并决定从创建一个fetch机器开始,它将负责处理我向服务器发出的每个请求。
我创建了一个简单的状态机:

import { createMachine, assign } from "xstate";

interface FetchContext {
  readonly results: any | null;
  readonly error: null | string;
}

type FetchServices = {
  readonly fetchData: {
    readonly data: any;
  };
}

export const fetchMachine = createMachine(
  {
    context: {
      results: null,
      error: null,
    },
    tsTypes: {} as import("./fetch.typegen").Typegen0,
    schema: {
      context: {} as FetchContext,
      services: {} as FetchServices,
    },
    id: "fetch",
    initial: "idle",
    states: {
      idle: {
        on: {
          FETCH: {
            target: "pending",
          },
        },
      },
      pending: {
        invoke: {
          src: "fetchData",
          onDone: { target: "success", actions: "setResults" },
          onError: { target: "failed", actions: "setError" },
        },
      },
      success: {
        on: {
          FETCH: {
            target: "pending",
          },
        },
      },
      failed: {
        on: {
          FETCH: {
            target: "pending",
          },
        },
      },
    },
  },
  {
    actions: {
      setResults: assign((context, event) => {
        return {
          results: event.data,
          error: null,
        };
      }),
      setError: assign((context, event) => {
        return {
          results: null,
          error: event.data as string,
        };
      }),
    },
  }
);

这里的主要问题是我想让这个fetchMachine负责具有不同返回类型的不同请求。正如你所看到的,在我的代码中获取的数据类型是“any”,我想修正这个问题。如果我只对一个请求使用fetchMachine,我会描述返回的对象类型,这样问题就不会出现了,但是在我的例子中,我想让这个fetchMachine重用于许多不同的服务。
第二个问题(与服务无关)是,如果我从“setError”操作的返回属性“error”中删除“as string”,typescript将报告“event.data“是未知类型,无法分配给“string| null”,正如我在FetchContext接口中描述的错误类型。在这种情况下,是否有方法正确地键入错误?

另外,在状态机中为每个“get”请求使用一个单独的抓取机是一个好的实践吗?我的意思是,有时候我曾经创建一个useFetch钩子来处理大多数请求,这就是我问这个问题的原因。

8e2ybdfx

8e2ybdfx1#

关于主要问题,我会使用接受泛型的工厂函数:

export const createFetchMachine = <T>() =>
  createMachine(
    {
      context: {
        results: null,
        error: null,
      },
      tsTypes: {} as import("./test.typegen").Typegen0,
      schema: {
        context: {} as {
          results: T | null;
          error: null | string;
        },
        services: {} as {
          fetchData: {
            data: T;
          };
        },
      },
      id: "fetch",

关于第二个问题,您可以阅读更多关于here的内容,当使用typegen时,应该像示例中那样强制转换错误类型。
至于通用的fetch机器,这是我开始使用xState时做的第一件事,但随着时间的推移,我发现简单的invoke promises对我来说工作得更好、更干净。

相关问题