Replies: 4 comments 2 replies
-
Hi @urugator @mweststrate Sorry for bothering you. I'd like to hear your opinion on that. Mobx already have flowResult, why not add one more zero-runtime helper? Even in the documentation example there is an issue: The variable |
Beta Was this translation helpful? Give feedback.
-
@kubk Found my way here too because I can't get the TS version of Flow's to the compile. I've been staring at the example for awhile now. I was keen to utilize the "cancel" method of flows, but its lot looking achievable. |
Beta Was this translation helpful? Give feedback.
-
A bit improved solution with a handy type alias, which I've been using in my projects. export type FlowGenerator<TReturn = void> = Generator<Promise<void>, TReturn, void>;
export function toFlowGeneratorFunction<TArgs extends unknown[], TReturn = void>(
fn: (...args: TArgs) => Promise<TReturn> | TReturn
): (...args: TArgs) => FlowGenerator<TReturn> {
return function* flowGeneratorFunction(...args: TArgs): FlowGenerator<TReturn> {
let value: TReturn = undefined as TReturn;
yield Promise.resolve(fn(...args)).then(result => {
value = result;
});
return value;
};
} I don't know when we could have something like this in Mobx or Mobx-utils, so I have published it as a package |
Beta Was this translation helpful? Give feedback.
-
I'm share my solution, or pattern. I'm using @flow.bound
private async *loadFAQList() {
try {
this.isLoading = true;
const faqList = await this.store.api.faq.fetchAll();
yield;
this.faqList = faqList;
} catch (e) {
yield;
console.error(e);
} finally {
this.isLoading = false;
}
} And some hacks. I can call async mobx flow actions, and await typed result. declare global {
// we can extend built-in AsyncGenerator 👀
// now, all async generators are promises also. No flowResult needs.
interface AsyncGenerator<T = unknown, TReturn = any, TNext = unknown> extends Promise<TReturn> {}
} Then we can do this: class Store {
// return type should be omitted
// return type infer as `AsyncGenerator<never, number[], unknown>` (and `Promise<number[]>` 😁)
@flow.bound async *method() {
return [1,2,3]
}
}
const example = async () => {
const store = new Store();
// return number[] (works!)
const result1 = await store.method()
// explicit type (works!)
const result2: number[] = await store.method()
// @ts-expect-error: Type number[] is not assignable to type string[]
const result3: string[] = await store.method();
} This is not perfect solution, types can still broken, in rare cases. But it works, as long as you follow the pattern. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Mobx
flow
is great because it allows to write async flows without wrapping observable modifications withaction
/runInAction
. But for TypeScript users it doesn't work well, because TS looses generator types:const a = yield 1; // type 'any' instead of 'number'
There is an open TS issue: microsoft/TypeScript#32523
In MST repo I've found a trick to get type inference working:
or if we want to avoid type casts:
It works with no issue:
But to make it working you should enable
downlevelIteration
in your tsconfig.jsonSo here is my question - should we add this utility function to Mobx codebase too and describe it's usage in documentation? I believe that Mobx
flow
is useless for TS users without this function. Ready to make a PR.We already have
flowResult
function for TS users. So it's better to come up with a better name rather thanresult
:)Beta Was this translation helpful? Give feedback.
All reactions