Immer: Version 1.9.1 produce Typescript type inference is partly broken

Created on 16 Dec 2018  路  10Comments  路  Source: immerjs/immer

Sample Code from readme.md:

const baseState = [
    {
        todo: "Learn typescript",
        done: true
    },
    {
        todo: "Try immer",
        done: false
    }
]

const nextState = produce(baseState, draftState => {
    draftState.push({todo: "Tweet about it", done: false })
    draftState[1].done = true
})

Type of nextState is void. It works correctly when I add return draftState at the end. Is this intended?

In my opinion there's no(?) case where produce shouldn't return anything. In other words: produce should always return something. Or am I wrong?


EDIT: I'm not entirely sure, but I think the typings should look something like that:

Old:

<S = any, R = never>(
        currentState: S,
        recipe: (this: Draft<S>, draft: Draft<S>) => void | R,
        listener?: PatchListener
    ): R

New:

<S, R>(
        currentState: S,
        recipe: (this: Draft<S>, draft: Draft<S>) => R,
        listener?: PatchListener
    ): R extends void ? S : R
bug released

Most helpful comment

I come from a Java background, and it's sometimes really confusing, because TypeScript's type system can do really weird things. It's really mighty. Sometimes I really miss some of it's features when writing Java code. And sometimes my brain starts to hurt when I look at some really complex TypeScript typings, like "extends with generics" or "infer" :D

But the good thing is: As long it's part of some external library (like yours) I don't have to care about the really complex stuff. Thanks for that!

All 10 comments

@benneq Yeah, your fix is spot on. The fix will be out in a sec.

Ah, I see, you were faster than me figuring this out :D

Oh actually, you need to do void extends R not R extends void, because otherwise it passes when R = number | void.

edit: Wait.. nevermind.

Thank you. That's really good to know :)

Yeah it's one of those rites of passage when wrapping your head around Typescript. 馃槅

Thanks for the bug report! 鉂わ笍

I come from a Java background, and it's sometimes really confusing, because TypeScript's type system can do really weird things. It's really mighty. Sometimes I really miss some of it's features when writing Java code. And sometimes my brain starts to hurt when I look at some really complex TypeScript typings, like "extends with generics" or "infer" :D

But the good thing is: As long it's part of some external library (like yours) I don't have to care about the really complex stuff. Thanks for that!

:tada: This issue has been resolved in version 1.9.2 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

Whoops, I forgot to remove the void from the other two function signatures. Let me know if it's a problem.

So far 1.9.2 works! But I guess, I have another issue with typings. I'll open a new issue in a few minutes.

Maybe you can fix the void stuff then for 1.9.3 :D

Was this page helpful?
0 / 5 - 0 ratings

Related issues

yuanalexwu picture yuanalexwu  路  5Comments

martinkadlec0 picture martinkadlec0  路  3Comments

steida picture steida  路  4Comments

phryneas picture phryneas  路  5Comments

DanielRuf picture DanielRuf  路  5Comments