Skip to content

Commit

Permalink
Fix flow typings mobx4 [requires TS3.6, mobx4] (#2161)
Browse files Browse the repository at this point in the history
* fix for flow typings

* fix async generator typing in flows
  • Loading branch information
xaviergonz authored and mweststrate committed Nov 7, 2019
1 parent c1d72a8 commit e988a52
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 42 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,4 @@
"pre-commit": "lint-staged"
}
}
}
}
36 changes: 6 additions & 30 deletions src/api/flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,35 +13,9 @@ export function isFlowCancellationError(error: Error) {

export type CancellablePromise<T> = Promise<T> & { cancel(): void }

export interface FlowYield {
// fake, only for typing
"!!flowYield": undefined
}

export interface FlowReturn<T> {
// fake, only for typing
"!!flowReturn": T
}

// we skip promises that are the result of yielding promises (except if they use flowReturn)
export type FlowReturnType<R> = IfAllAreFlowYieldThenVoid<
R extends FlowReturn<infer FR>
? FR extends Promise<infer FRP>
? FRP
: FR
: R extends Promise<any>
? FlowYield
: R
>

// we extract yielded promises from the return type
export type IfAllAreFlowYieldThenVoid<R> = Exclude<R, FlowYield> extends never
? void
: Exclude<R, FlowYield>

export function flow<R, Args extends any[]>(
generator: (...args: Args) => IterableIterator<R>
): (...args: Args) => CancellablePromise<FlowReturnType<R>> {
generator: (...args: Args) => Generator<any, R, any> | AsyncGenerator<any, R, any>
): (...args: Args) => CancellablePromise<R> {
if (arguments.length !== 1)
fail(
!!process.env.NODE_ENV && `Flow expects one 1 argument and cannot be used as decorator`
Expand All @@ -53,7 +27,9 @@ export function flow<R, Args extends any[]>(
const ctx = this
const args = arguments
const runId = ++generatorId
const gen = action(`${name} - runid: ${runId} - init`, generator).apply(ctx, args)
const gen = action(`${name} - runid: ${runId} - init`, generator as (
...args: Args
) => Generator<any, R, any>).apply(ctx, args)
let rejector: (error: any) => void
let pendingPromise: CancellablePromise<any> | undefined = undefined

Expand Down Expand Up @@ -119,7 +95,7 @@ export function flow<R, Args extends any[]>(
rejector(e) // there could be a throwing finally block
}
})
return (res as CancellablePromise<R>) as any
return res as CancellablePromise<R>
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/types/observablemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ export class ObservableMap<K = any, V = any>
return makeIterable({
next() {
return nextIndex < self._keys.length
? { value: self.get(self._keys[nextIndex++]), done: false }
? { value: self.get(self._keys[nextIndex++])!, done: false }
: { value: undefined as any, done: true }
}
})
Expand Down
19 changes: 15 additions & 4 deletions test/base/typescript-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1557,9 +1557,9 @@ test("it should support asyncAction as decorator (ts)", async () => {
class X {
@observable a = 1

f = mobx.flow(function* f(initial: number): any {
f = mobx.flow(function* f(this: X, initial: number) {
this.a = initial // this runs in action
this.a += yield Promise.resolve(5)
this.a += yield Promise.resolve(5) as any
this.a = this.a * 2
return this.a
})
Expand Down Expand Up @@ -1590,7 +1590,7 @@ test("flow support async generators", async () => {
total += number
}
return total
} as any) // TODO: fix typings
})

const p = start()
const res = await p
Expand All @@ -1615,7 +1615,7 @@ test("flow support throwing async generators", async () => {
total += number
}
return total
} as any) // TODO: fix typings
})

const p = start()
try {
Expand Down Expand Up @@ -1647,3 +1647,14 @@ test("verify #1528", () => {

expect(appState.timer).toBe(0)
})

test("type of flows that return promises", async () => {
mobx.configure({ enforceActions: "observed" })

const f = mobx.flow(function* f() {
return Promise.resolve(5)
})

const n: number = await f()
expect(n).toBe(5)
})
12 changes: 6 additions & 6 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7945,9 +7945,9 @@ ts-jest@^24.0.0:
yargs-parser "10.x"

tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
version "1.9.3"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==
version "1.10.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==

tsutils@^3.7.0:
version "3.10.0"
Expand Down Expand Up @@ -7994,9 +7994,9 @@ typedarray@^0.0.6:
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=

typescript@^3.3.3333:
version "3.4.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.4.tgz#aac4a08abecab8091a75f10842ffa0631818f785"
integrity sha512-xt5RsIRCEaf6+j9AyOBgvVuAec0i92rgCaS3S+UVf5Z/vF2Hvtsw08wtUTJqp4djwznoAgjSxeCcU4r+CcDBJA==
version "3.6.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.6.4.tgz#b18752bb3792bc1a0281335f7f6ebf1bbfc5b91d"
integrity sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg==

uglify-js@^3.1.4:
version "3.5.5"
Expand Down

0 comments on commit e988a52

Please sign in to comment.