Wednesday, March 20, 2019

Flattening redux state while maintaining navigability

Let's say you have this interface for mapStateToProps:

// file 1

export interface ILoggedUserState
{
    username: string;
    email: string;
    lastLogged: Date;
}

// file 2

export interface IAllState
{
    loggedUser: ILoggedUserState;
    chosenTheme: IChosenTheme;
    menu: IMenu;
}

// file 3

interface IPropsToUse
{
    loggedUser: ILoggedUserState;
    chosenTheme: IChosenTheme;
}

export const mapStateToProps = ({loggedUser, chosenTheme}: IAllState): IPropsToUse => ({
    loggedUser,
    chosenTheme
});




And you want to flatten or use only a few fields from ILoggedUserState, say we only want to use the username only:

interface IPropsToUse
{
    username: string;
    chosenTheme: IChosenTheme;
}

export const mapStateToProps = ({loggedUser: {username}, chosenTheme}: IAllState): IPropsToUse => ({
    username,
    chosenTheme
});


The downside of that code is it cannot convey anymore where the IPropsToUse's username property come from.

Here's a better way to convey that IPropsToUse's username come frome ILoggedUserState's username field.

interface IPropsToUse
{
    username: ILoggedUserState['username'];
    chosenTheme: IChosenTheme;
}

export const mapStateToProps = ({loggedUser: {username}, chosenTheme}: IAllState): IPropsToUse => ({
    username,
    chosenTheme
});


The syntax looks odd, but it works. With the code above, we can convey that IPropsToUse's username come from ILoggedUserState's username, and IPropsToUse's username also receives the type of ILoggedUserState's username.

No comments:

Post a Comment