7
votes

I am not able to type the "state" parameter of a mapStateToProps

If I just change state : any instead of state: AppState it works and no error. But I would like to have a correct typing for my state parameter.

For now, I have this error on the mapStateToProps param of the connect()

No overload matches this call. The last overload gave the following error. Argument of type '(state: { quiz: IQuizInitialState; }) => StateProps' is no assignable to parameter of type 'MapStateToPropsParam'. Cannot assign the type '(state: { quiz: IQuizInitialState; }) => StateProps' to type 'MapStateToPropsFactory'. Parameters 'state' and 'initialState' are not compatible. Property 'quiz' is missing in type '{}' but required in type '{ quiz: IQuizInitialState; }'.ts(2769)

interface OwnProps {

}
interface StateProps {

}
interface DispatchProps {

}

type Props = OwnProps & StateProps & DispatchProps;


export class App extends Component<Props> {

  render() {
    return (
     <div>Hey</div>
    );
  }
}

const mapStateToProps = (state: AppState): StateProps => ({ 
})

const mapDispatchToProps = (dispatch: ThunkDispatch<{}, {}, AnyAction>): DispatchProps => {
    return {
    }
}


// The args 'mapStateToProps' generate the error
export default connect<StateProps,DispatchProps,OwnProps>(mapStateToProps, mapDispatchToProps)(App)

This is my rootReducer :

import { combineReducers } from 'redux';
import { QuizReducer } from './quiz';

const rootReducer = combineReducers({
    quiz: QuizReducer
});

export type AppState = ReturnType<typeof rootReducer>


export default rootReducer;

And the single reducer is :

import { TYPES } from '../actions/action-types';
import { IQuizListItem, Action } from '../models/index';
import { AnyAction } from 'redux';


export interface IQuizInitialState {
    quizListItem: IQuizListItem[]
}
const quizInitialState: IQuizInitialState = {
    quizListItem: []
}
export const QuizReducer = (state = quizInitialState, action: AnyAction): IQuizInitialState => {
    switch (action.type) {
        case TYPES.getQuizListItems:
            return {
                ...state,
                quizListItem: (action as Action<IQuizListItem[]>).payload
            }

        default:
            return state
    }
}

Thank you by advance guys !

1
What is AppState in mapStateToProps?Mohit

1 Answers

14
votes

The type of your state is the same type you use for the whole state. since mapStateToProps takes the whole state to pass it down to selectors. in your case I believe this would be the correct type IQuizInitialState.

const mapStateToProps = (state: IQuizInitialState): StateProps => ({ 

})

EDIT

In your comment you mention IQuizInitialState isnt your whole application state. Then that one is not the one you need. You need a type for the whole application state. To achieve that you could create an interface for every single reducer type meaning your IQuizInitialState but for the other reducers into a single interface.

Ill have to asume here since I dont have your code base but consider

combineReducers({potato: quizReducer, tomato: otherReduzer})

you'll need a type

interface IApplicationState {
potato: IQuizInitialState;
tomato: IOTherInterfaceYouDefinedForThisReducer;
}

your combineReducers will probable look like :

combineReducers<IApplicationState>({
  potato: quizReducer,
  tomato: otherReduzer
});

I hope you get the idea.

EDIT 2 After reading your last comment I noticed you are asking for the mapStateToProps with two arguments. and you are just defining one. Your connect generics seems wrong then. you should consider the following:

connect<StateProps, DispatchProps, Props, IApplicationState>

where:

  • StateProps : describes what was returned by mapStateToProps()
  • DispatchProps: describes what is returned by dispatchToProps()
  • Props: Your component props
  • IApplicationState: Represents your Apps Redux whole state