reduxjs / reselect

Selector library for Redux
MIT License
19.04k stars 670 forks source link

How do I make optional parameters? #473

Closed denchen closed 3 years ago

denchen commented 4 years ago

I'm trying to type my createSelector() function for use with Redux's useSelector(), but I'm not sure how to type optional parameters.

Extending the example from the README:

const getTodos = (state, props?: Record<string, string>) =>
  state.todoLists[props ? props.listId : 'foo'].todos

const getTodos = createSelector(
  [ getTodos ],
  (todos) => {
    // Irrelevant logic here
  }
)

If I type props as optional like in the above, then using the selector as such:

getTodos(state, { listId: 'meh' })`

It then complains that it expected 1 argument, but got 2

But if I change the signature to

const getTodos = (state, props: Record<string, string>) =>
  state.todoLists[props ? props.listId : 'foo'].todos

Then use the selector as such:

getTodos(state)`

It then complains: Expected at least 2 arguments, but got 1.

So is there a way to be able to use one selector for both scenarios?

joedski commented 3 years ago

My suggestion based only on what I see here:

// baseSelectors.ts
export const getTodos = (state, props: { listId: string }) =>
  // TODO: what if todoLists[props.listId] is undefined?
  state.todoLists[props.listId].todos

export const getDefaultTodos = (state) => getTodos(state, { listId: 'foo '})
// other.js
import * as baseSelectors from './baseSelectors.js'

const getTodos = createSelector(
  [ baseSelectors.getTodos ],
  (todos) => {
    // Irrelevant logic here
  }
)
  1. Less need to worry about whatever type magic createSelector() is doing.
  2. Tells anyone coming to the code later what's up.

Without any further context about what you're trying to accomplish, that's all I can come up with. Usually though, obvious and explicit is better than trying to cram everything into a single function with optional parameters.