- Notifications
You must be signed in to change notification settings - Fork27
Description
My package,typescript-fsa-redux-thunk and my attempts to refactor it have failed, and this also affectstypescript-fsa-reducers. The best way to explain the errors I'm getting is to post a test case and explain where the errors are:
import{Dispatch,applyMiddleware,bindActionCreators,createStore}from'redux';importthunk,{ThunkAction}from'redux-thunk';importactionCreatorFactory,{AsyncActionCreators,ActionCreatorFactory}from'typescript-fsa';import{reducerWithInitialState}from'typescript-fsa-reducers';/** * It's either a promise, or it isn't */typeMaybePromise<T>=T|Promise<T>;/** * A redux-thunk with the params as the first argument. You don't have to * return a promise; but, the result of the dispatch will be one. */exporttypeAsyncWorker<State,Params,Result,Extra=any>=(params:Params,dispatch:Dispatch<State>,getState:()=>State,extra:Extra)=>MaybePromise<Result>;/** * Bind a redux-thunk to typescript-fsa async action creators *@param actionCreators - The typescript-fsa async action creators *@param asyncWorker - The redux-thunk with the params as the first argument *@returns a regular redux-thunk you can pass to dispatch() */exportconstbindThunkAction=<State,P,S,E,ExtraArg=any>(actionCreators:AsyncActionCreators<P,S,E>,asyncWorker:AsyncWorker<State,P,S,ExtraArg>)=>(params:P):ThunkAction<Promise<S>,State,ExtraArg>=>(dispatch,getState,extra)=>{dispatch(actionCreators.started(params));returnPromise.resolve(asyncWorker(params,dispatch,getState,extra)).then(result=>{dispatch(actionCreators.done({ params, result}));returnresult;}).catch((error:E)=>{dispatch(actionCreators.failed({ params, error}));throwerror;});};/** * Factory function to easily create a typescript-fsa redux thunk *@param factory - typescript-fsa action creator factory *@returns an object with the async actions and the thunk itself */exportconstasyncFactory=<State,E=Error,ExtraArg=any>(factory:ActionCreatorFactory)=><P,S>(type:string,fn:AsyncWorker<State,P,S,ExtraArg>)=>{constactions=factory.async<P,S,E>(type);return{async:actions,action:bindThunkAction(actions,fn)};};/** * Passing the result of this to bindActionCreators and then calling the result * is equivalent to calling `store.dispatch(thunkAction(params))`. Useful for * when you pass it to `connect()` as the actionCreators map object. *@param thunkAction - The thunk action *@returns thunkAction as if it was bound */exportconstthunkToAction=<P,R,S,ExtraArg>(thunkAction:(params:P)=>ThunkAction<R,S,ExtraArg>):((params:P)=>R)=>thunkActionasany;/****** TEST CODE ******/interfaceSomeState{hmm:number;}constcreate=actionCreatorFactory('something');constcreateAsync=asyncFactory<SomeState>(create);constsomeAction=create<string>('SOME_ACTION');consttest=createAsync<{arg:string;},number>('ASYNC_ACTION',asyncparams=>{console.log(params);return100;});constinitial:SomeState={hmm:0};constreducer=reducerWithInitialState(initial).case(someAction,state=>state).case(test.async.started,state=>state).case(test.async.failed,state=>state).case(test.async.done,(state,{ result})=>({ ...state,hmm:result}));if(module===require.main){conststore=createStore(reducer,applyMiddleware(thunk));constactions=bindActionCreators({test:thunkToAction(test.action)},store.dispatch);actions.test({arg:'test'}).then(result=>console.log(result)).catch(err=>console.log(err));}
There are only three errors, and interestingly, all occurring inside of mybindThunkAction function where the async actions are called:
// Line 46:dispatch(actionCreators.started(params));// Cannot invoke an expression whose type lacks a call signature. Type '({ type: string; match: (action: AnyAction) => action is Action<P>; } & ((payload?: P | undefined...' has no compatible call signatures.// Line 49:dispatch(actionCreators.done({ params, result}));// Argument of type '{ params: P; result: S; }' is not assignable to parameter of type 'Optionalize<{ params: P; result: S; }>'.// Type '{ params: P; result: S; }' is not assignable to type '{ [P in (P extends undefined ? never : "params") | (S extends undefined ? never : "result")]: { p...'.// Line 53:dispatch(actionCreators.failed({ params, error}));// Argument of type '{ params: P; error: E; }' is not assignable to parameter of type 'Optionalize<{ params: P; error: E; }>'.// Type '{ params: P; error: E; }' is not assignable to type '{ [P in (P extends undefined ? never : "params") | (E extends undefined ? never : "error")]: { pa...'.
I've been fiddling with my own code for hours, and I can't seem to figure out why this is happening. Passing normal parameters to these action creators outside ofbindThunkAction works fine.
Another weirdness: even with these errors, the reducer seems to work; but, the types ofparams andresult, etc have a weird optional-like, for example:number | { undefined & number }.
If one ignores the errors and runs the code withts-node, it executes without errors. Am I losing it?