I have the following state type for my redux reducer:
export interface CharactersState {
characters: CharacterType[];
error: string | null;
isFetching: boolean;
}
I am then using this state type with combineReducer to create my store:
const initialState: CharactersState = {
characters: [],
error: null,
isFetching: true // initiated with fetching true on app load
};
const characters = (state = initialState, action: CharacterActionsType) => {
switch (action.type) {
// commented out reducer logic here since it is not relevant
//...
default:
return state;
}
};
const rootReducer = combineReducers({
characters
});
export type RootStateType = ReturnType<typeof rootReducer>;
export default rootReducer;
I am then using this rootReducer in a component controller:
const getCharacters = (state: RootStateType): CharactersState =>
state.characters;
export const makeCharactersList = createSelector<
RootStateType,
CharactersState,
CharacterListType[]
>(getCharacters, characters => {
return characters.characters
.map(character => {
return {
_id: character._id,
name: character.name,
description: character.description
};
})
.sort((a, b) => {
return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
});
});
const mapStateToProps = (state: RootStateType) => {
return {
characters: makeCharactersList(state)
};
};
const mapDispatchToProps = (dispatch: any) => {
return {
handleDeleteClick: (_id: string | null) => {
dispatch(postDeleteCharacter(_id));
}
};
};
const connector = connect(mapStateToProps, mapDispatchToProps);
export type PropsFromRedux = ConnectedProps<typeof connector>;
export default connector(CharacterSidebar);
The controller is rendered in the parent component without passing any props:
<Sidebar />
How do I write the correct type definition for makeCharactersList
? It seems that createSelector
should take the types of State, OwnProps, ConnectedProps - in my case it seems that OwnProps would just be an empty object?
But when I set the type definition to:
createSelector<
RootStateType,
{},
CharacterListType[]
I get the following error:
Property 'characters' does not exist on type '{}'.
There are multiple overloads for createSelector
, but the one that you are matching is this:
export function createSelector<S, R1, T>(
selector: (state: S) => R,
combiner: (res: R1) => T,
): OutputSelector<S, T, (res: R1) => T>;
The three generics are:
S
- the type of the root state - RootStateType
R1
- the value selected by the first selector, which is also the input for the combiner - CharactersState
T
- the value that you return from the combiner - Pick<CharacterType, '_id' | 'name' | 'description'>[]
(an array of characters with only the selected properties)Probably your CharacterListType
is an alias for the picked properties in #3? If so, then you had it correct in your code block.
export const makeCharactersList = createSelector<
RootStateType,
CharactersState,
CharacterListType[]
>(getCharacters, characters => {
...