Skip to content

Function inference fails when a final argument is supplied after rest via destructured tuples #43122

Closed
@poteat

Description

@poteat

Bug Report

I'm not sure whether inference failures are usually classified as suggestions or bugs. Sorry if I've assigned this the wrong label!

📖 Context / Introduction

I'm trying to improve the typings for an open source library called reselect. Their createSelector function first takes in an arbitrary amount of "selector" functions that take in one parameter as a given state type, and then takes in one final additional function which combines the results of the previous functions. I have an implementation, but inference isn't working as I expect.

⏯ Playground Link

Playground link with relevant code

💻 Code

export type Selector<State> = (state: State) => unknown;
export type SelectorTuple<State> = Selector<State>[];

export type ExampleState = {
  foo: "foo";
  bar: 42;
};

export function createSelector<S extends SelectorTuple<ExampleState>>(
  ...selectors: [...selectors: S, f: (x: any) => any] // f causes issues
) {
  console.log(selectors);
}

createSelector(
  (x) => x.foo, // x is of 'any' type rather than ExampleState
  (x) => x.bar, // x is of 'any' type rather than ExampleState
  () => 42
);

🙁 Actual behavior

In the createSelector call, all of the x parameters have an implicit type of any, instead of ExampleState.

Observations:

  • When the last tuple element is removed from the type, inference works.
  • When the last tuple element is made to have zero parameters, inference works.
  • When the last tuple element is made to be anything except a function or any, inference works.

For some reason, the compiler is having difficulty inferring the rest parameters in this case.

🙂 Expected behavior

I would expect the type system to infer that the x parameter of all functions except the last is ExampleState.

Metadata

Metadata

Assignees

Labels

Fix AvailableA PR has been opened for this issueNeeds InvestigationThis issue needs a team member to investigate its status.RescheduledThis issue was previously scheduled to an earlier milestone

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions