Typed yield expression in MobX-State-Tree flow
Asked Answered
C

2

6

The recommended way to do asynchronous actions in MobX-state-tree (MST) is to use flow, which takes a generator function as first argument in which every promise should be yielded.

yield expressions are of type any in TypeScript, but is there any way to automatically type a yield expression in MST?

Example

import { flow, types } from "mobx-state-tree";

type Stuff = { id: string; name: string };

function fetchStuff(): Promise<Stuff[]> {
  return new Promise((resolve) => {
    resolve([
      { id: "1", name: "foo" },
      { id: "2", name: "bar" }
    ]);
  });
}

const Thing = types.model({
  id: types.identifier,
  name: types.string
});

const ThingStore = types
  .model({
    things: types.array(Thing)
  })
  .actions((self) => ({
    fetchThings: flow(function* () {
      // "stuff" is of type "any"!
      const stuff = yield fetchStuff();
      self.things.replace(stuff);
    })
  }));
Contraceptive answered 19/12, 2020 at 20:18 Comment(0)
C
12

toGenerator can be used to convert a promise to a generator yielding that promise. This together with yield* instead of yield (which is made available by setting downlevelIteration to true in the TypeScript compiler options) makes it so the promise return type is retained.

import { flow, types, toGenerator } from "mobx-state-tree";

type Stuff = { id: string; name: string };

function fetchStuff(): Promise<Stuff[]> {
  return new Promise((resolve) => {
    resolve([
      { id: "1", name: "foo" },
      { id: "2", name: "bar" }
    ]);
  });
}

const Thing = types.model({
  id: types.identifier,
  name: types.string
});

const ThingStore = types
  .model({
    things: types.array(Thing)
  })
  .actions((self) => ({
    fetchThings: flow(function* () {
      // "stuff" is now of type "Stuff[]"!
      const stuff = yield* toGenerator(fetchStuff());
      self.things.replace(stuff);
    })
  }));
Contraceptive answered 19/12, 2020 at 20:18 Comment(0)
E
0

It's also possible to use typescript or babel transform plugins to do that translation only later:

In native Typescript, it's sadly not possible (yet) to describe the return type of yield - see details in this issue

Earthshaker answered 20/8, 2023 at 9:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.