tomole
tomole

Reputation: 1006

How to use createSelector with parameter and Typescript?

I use redux-toolkit to generate selectors. I want to use them in my own custom reselect selectors with parameters. But I do not know how to type the return type of my selector?

const selectOrganizationName = (id: string): ??? =>
  createSelector(
    [(state: RootState) => organizationSelectors.selectById(state, id)],
    organization => organization.name
  );

export default selectOrganizationName;
Missing return type on function.eslint@typescript-eslint/explicit-module-boundary-types

Upvotes: 15

Views: 29655

Answers (2)

nanobar
nanobar

Reputation: 66355

For me as soon as I added a selector for a custom param, it broke the TS of the entire file (all the selectors return types became any).

export const mappedFavouritesSelector = createSelector(
  // ...Other selectors...
  (_, hkSpotEnabled) => hkSpotEnabled,
  (
    // ...Other selector results...
    hkSpotEnabled,
  )

But the issue went away when I pulled out the param selector to a const function 🤷‍♂️:

const hkSpotEnabledSelector = (_: RootState, hkSpotEnabled: boolean) =>
  hkSpotEnabled;

export const mappedFavouritesSelector = createSelector(
  // ...Other selectors...
  hkSpotEnabledSelector,
  (
    // ...Other selector results...
    hkSpotEnabled,
  )

Upvotes: 1

Linda Paiste
Linda Paiste

Reputation: 42188

Keep in mind that this warning only appears due to your ESLint settings which require explicit return types. Typescript is able to infer the type properly.

When you call the selectOrganizationName function, you return a selector that takes a RootState and returns an organization name which is string | undefined.

type Return = (state: RootState) => string | undefined;

const selectOrganizationName = (id: string): Return =>
  createSelector(
    [(state: RootState) => organizationSelectors.selectById(state, id)],
    (organization) => organization?.name
  );

However you likely have lots of selectors that you want to create return types for, so you can create a helper type that includes your RootState automatically and just requires you to set the type of the selection.

type Selector<S> = (state: RootState) => S;

const selectOrganizationName = (id: string): Selector<string | undefined> =>
  createSelector(
    [(state: RootState) => organizationSelectors.selectById(state, id)],
    (organization) => organization?.name
  );

Typescript Playground Link

Upvotes: 20

Related Questions