ReturnType for a specifc overload of a generic function

Viewed 130

So I was looking if there was a better way to write typings for reduxs bindActionCreators function.

That function accepts a map object of functions and a dispatch function and optimally should return another map object that contains functions that take the same arguments, but return the return value of the dispatch function as if it were passed the return value of the initial function.

So,

const bound = bindActionCreators({ foo: () => "bar" }, dispatch);
bound.foo() // this should return the result of calling `dispatch("bar")`.

Dispatch in this case is just about any function - that is what makes it interesting.

I tried implementing that, but all I'm getting as a final type is unknown. Am I missing something essential here or is this just not possible?

import {ActionCreatorsMapObject, Dispatch,AnyAction} from 'redux';

declare function bindActionCreators<A, M extends ActionCreatorsMapObject<A>, D extends Dispatch>(
  actionCreators: M,
  dispatch: D
): { 
  [K in keyof M]: D extends (action: ReturnType<M[K]>) => infer Ret ? (...args: Parameters<M[K]>) => Ret : M[K] 
}

// usage:

import {ThunkDispatch} from 'redux-thunk'

declare const thunkDispatch: ThunkDispatch<{}, undefined, AnyAction>;

const bound = bindActionCreators({
  normalAction: (foo: string) => ({type: "normalAction", foo}),
  thunkAction: (foo: string) => () => Promise.resolve({type: "thunk", foo}),
}, thunkDispatch)

// these are unfortunately `unknown`, not the expected types
const normal: {type: "normalAction", foo: string} = bound.normalAction("asd");
const thunk: Promise<{type: "normalAction", foo: string}> = bound.thunkAction("qwe")

TypeScript playground

0 Answers
Related