immerjs / immer

Create the next immutable state by mutating the current one
https://immerjs.github.io/immer/
MIT License
27.65k stars 848 forks source link

Incorrect type inference with currying #831

Open sarmong opened 3 years ago

sarmong commented 3 years ago

🐛 Bug Report

When using currying, produce doesn't return the original type

Link to repro

https://codesandbox.io/s/immer-sandbox-forked-342jd?file=/src/index.ts

To Reproduce

Use produce function without data and check the return type.

Observed behavior

Curried produce returns:

const updatedCache2: (oldAssignments: Assignment[]) => <Base extends readonly {
    readonly assignmentBk: string;
    readonly contentBk: string;
    readonly createdDate: Date;
    readonly startDate: Date;
    readonly dueDate: Date;
    readonly done: boolean;
}[]>(base?: Base) => Base

Expected behavior

Curried produce returns the original type.

I need it, because it fails when using with Ramda's pipe function.

Environment

We only accept bug reports against the latest Immer version.

childrentime commented 2 years ago

For the function updateCache2 , arguments will be narrow to Immutable<Assignment[]>. If we don't want this, we can specify the generic state. However, type of function updatedCache3 is (state: Assignment[] | undefined) => Assignment[] .Maybe this '?' can be removed?

<State>(
  recipe: (
      state: Draft<State>,
      initialState: State
              ) => ValidRecipeReturnType<State>
): (state?: State) => State
childrentime commented 2 years ago

it seems like this function

const updatedCache3 = produce<Assignment[]>((draft) => {
  const updatedAssignment = draft.find(
    ({contentBk}) => contentBk === assignment.contentBk
  )
  if (updatedAssignment) {
    updatedAssignment.done = !updatedAssignment.done
  }
})

will map to

 <State>(recipe: (state: Draft<State>, initialState: State) => ValidRecipeReturnType<State>): (state?: State) => State;

not map to

  <State>(recipe: (state: Draft<State>) => ValidRecipeReturnType<State>): (state: State) => State;