Typescript with Redux, how to use a connection without re-declaring an action definition?

I am having some inconvenience with typescript and redux-thunk effects.

Basically, my components actively use connect-redux to bind the creators of the action, the problem is that when I create an interface for these redux actions inside the component, I need to re-declare the function definition because it gets lost on the connection call.

Here is a sample code:

Action creator

import api from './api'; import { Dispatch } from 'redux'; import { IReduxAction } from 'model'; export const FETCH_ENTITY = 'location/FETCH_ENTITY'; export function fetchEntity(id: string) { return (dispatch: Dispatch<IReduxAction>) => { dispatch({type: `${FETCH_ENTITY}_REQUEST`, payload: {id}}); return api.fetchEntity(id) .then((res) => { dispatch({ type: `${FETCH_ENTITY}_DONE`, payload: res }); return res; }) .catch((err) => { dispatch({type: `${FETCH_ENTITY}_FAIL`, payload: err, error: true}); throw err; }); }; } 

component

 import * as React from 'react'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; import { fetchEntity, } from 'actions'; interface IStateProps { startingEntities: any[]; } interface IDispatchProps { fetchEntity: (id: string) => Promise<any>; // <- this is what I'm trying to get rid of, basically whenever I change the action creator I have to change this definition everytime } class Dashboard extends React.Component<IStateProps & IDispatchProps, void> { public render() { return (<div>...RENDER SOMETHING...</div>); } } const mapStateToProps = (state: any, ownProps: any) => { const startingEntities = foo(); // not important return { startingEntities, }; }; const mapDispatchToProps = (dispatch: any) => { return bindActionCreators({ fetchEntity }, dispatch); }; export default connect<IStateProps, IDispatchProps, void>(mapStateToProps, mapDispatchToProps)(Dashboard); 

Is it possible to declare this created action object without having to re-declare it every time in every file?

+5
source share
3 answers

You do not need to determine the type of function again. You can use typeof :

 interface IDispatchProps { fetchEntity: typeof fetchEntity } 
+7
source

I am not very familiar with TypeScript (basically I just made index.d.ts files for library interfaces), but you should be able to get a type system to do this by typing fetchEntity and exporting it to use for IDispatchProps . Sort of

 //... import { ThunkAction } from 'redux-thunk' //... export interface FetchEntity { (id: string): ThunkAction<Promise<any>, IReduxAction, any>; } //... export const fetchEntity: FetchEntity = (id: string) => { return (dispatch: Dispatch<IReduxAction>) => { //... }; } 

And then you can import it and use the same definition

 //... import { fetchEntity, FetchEntity } from 'actions'; //... interface IDispatchProps { fetchEntity: FetchEntity } //... 
+1
source

I'm not sure to understand the design pattern you're looking for, but the action creator is just a simple object with the type of property that the reducer needs when it uses it.

Therefore, I would suggest that the best way to handle this is to get a dedicated file with your actions, which you will export and then import. Your logic about choosing an action for dispatc will be in your component behavior, which seems better to me.

Hope this helps and solve your problem :)

0
source

Source: https://habr.com/ru/post/1269145/


All Articles