Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type loss in createSelector with inline function declarations passed as separate arguments #666

Open
aryaemami59 opened this issue Dec 17, 2023 · 0 comments

Comments

@aryaemami59
Copy link
Contributor

Overview

When using createSelector from Reselect, I've encountered a rare edge case affecting TypeScript type inference. This issue arises specifically when passing input selectors as separate inline arguments composed of inline function declarations.


Detailed Behavior

  • ✔️ Working Scenario 1: Input selectors as inline function declarations in a single array works fine.
  • ✔️ Working Scenario 2: Input selectors as function declarations passed as separate arguments, defined outside of createSelector works fine.
  • ❌ Problematic Scenario: Inline function declarations as separate arguments in createSelector cause TypeScript to resolve the parameter types of the result function to unknown.

Reproduction

Here are the different scenarios for clarity:

✔️ Scenario 1 - Works Fine:

const selectTodoIds = createSelector(
  [
    function selectTodos(state: RootState) {
      return state.todos;
    },
    function selectId(state: RootState, id: number) {
      return id;
    },
  ],
  (todos, id) => todos.map(todo => todo.id)
);

✔️ Scenario 2 - Works Fine:

function selectTodos(state: RootState) {
  return state.todos;
}

function selectId(state: RootState, id: number) {
  return id;
}

const selectTodoIds = createSelector(selectTodos, selectId, (todos, id) =>
  todos.map(todo => todo.id)
);

❌ Problematic Scenario - Result Function Loses its Types:

const selectTodoIds = createSelector(
  function selectTodos(state: RootState) {
    return state.todos;
  },
  function selectId(state: RootState, id: number) {
    return id;
  },
  (todos, id) => todos.map(todo => todo.id)
  // ❌ Here, both `todos` and `id` resolve to a type of `unknown`.
);

Impact

Although this situation may not happen very often and this issue may not be common, it's important to document for those who might encounter it.


Workarounds

Several simple workarounds include:

  1. Using arrow functions instead of inline function declarations.
  2. Grouping input selectors into a single array.
  3. Defining the function declarations outside of createSelector.

Either one of these methods solves the problem.


Conclusion

This might be one of those issues that might eventually just go away as TypeScript gets better, but documenting it with potential workarounds can assist others potentially facing similar challenges.


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant