diff --git a/types/index.d.ts b/types/index.d.ts index 5b079cf..acd13d4 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -6,7 +6,11 @@ // TODO remove this eslint-disable // eslint-disable-next-line import/no-unresolved -import { ActionMatchingPattern, Buffer } from "@redux-saga/types"; +import { + ActionMatchingPattern, + Buffer, + SagaIterator, +} from "@redux-saga/types"; import { Action } from "redux"; import { TakeableChannel, @@ -45,6 +49,14 @@ import { CallEffectDescriptor, } from "redux-saga/effects"; +export type ExtractReturnValue = ReturnType extends SagaIterator< + infer SagaReturnType +> + ? SagaReturnType + : ReturnType extends Promise + ? PromiseReturnType + : ReturnType; + export type SagaGenerator> = Generator< E, RT @@ -184,22 +196,28 @@ export function putResolve( action: A, ): SagaGenerator>; -export function call any>( - fn: Fn, +export function call( + fn: (...args: Args) => Return, ...args: Args -): SagaGenerator, CallEffect>>; +): SagaGenerator< + ExtractReturnValue, + CallEffect> +>; + export function call< - Args extends any[], + FnName extends keyof Ctx, + Args extends unknown[], + Return, + Fn extends (this: Ctx, ...args: Args) => Return, Ctx extends { - [P in Name]: (this: Ctx, ...args: Args) => any; + [Key in FnName]: Fn; }, - Name extends string, >( - ctxAndFnName: [Ctx, Name], + ctxAndFnName: [Ctx, FnName], ...args: Args ): SagaGenerator< - SagaReturnType, - CallEffect> + ExtractReturnValue, + CallEffect> >; export function call< Args extends any[], diff --git a/types/index.test.ts b/types/index.test.ts index 5745d5e..def9259 100644 --- a/types/index.test.ts +++ b/types/index.test.ts @@ -251,4 +251,12 @@ function* mySaga(): Effects.SagaGenerator { yield* Effects.spawn([obj, "outer"], emitter, handler); yield* Effects.spawn({ context: obj, fn: obj.outer }, emitter, handler); yield* Effects.spawn({ context: obj, fn: "outer" }, emitter, handler); + + const identity = (x: T): T => x; + // $ExpectType "foo" + yield* Effects.call(identity, "foo" as const); + + const ctx = { identity } as const; + // $ExpectType "foo" + yield* Effects.call([ctx, "identity"], "foo" as const); }