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);
    })
  }));
Tholle
  • 108,070
  • 19
  • 198
  • 189

2 Answers2

10

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);
    })
  }));
Tholle
  • 108,070
  • 19
  • 198
  • 189
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

TeNNoX
  • 1,899
  • 3
  • 16
  • 27