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

Feature Request: Enhance useImmer's type #91

Closed
bglgwyng opened this issue Jul 26, 2021 · 1 comment
Closed

Feature Request: Enhance useImmer's type #91

bglgwyng opened this issue Jul 26, 2021 · 1 comment

Comments

@bglgwyng
Copy link

bglgwyng commented Jul 26, 2021

Sometimes I use nullable state with useImmer, like following example.

type Dog = {
  name: string,
  age: number,
};

function SomeComponent() {
  const [dog, updateDog] = useImmer<Dog | null>(null);
  return (
    dog
    ? <button 
         onClick={() => 
           updateDog((newDog) => { newDog!.age += 1 })}>
        Increase age!
      </button>
    :  <button onClick={() => updateDog(() => ({ name: "John", age: 1 }))}>New dog!</button>
  );
}

This pattern occurs when dog cannot always be defined when SomeComponent is mounted.

The problem is that even after I narrow dog's type to a non-nullable one, I have to add a non-null assertion to newDog.
If Dog has a large definition and the update is verbose, I have to put exclamation marks every time I refer to newDog in updateDogcallback.
However, when newDog is null, any update I would try is meaningless, while returning the new Dog object like in New dog! button's onClickhandler is the only valid and expected action.

So I think that removing the nullability of the state type is doable for convenience.

The current definition of useImmer reads as follows.

export declare function useImmer<S = any>(initialValue: S | (() => S)): [S, (f: (draft: Draft<S>) => void | S) => void];

What about changing it to the following one?

export declare function useImmer<S = any>(initialValue: S | (() => S)): [S, (f: (draft: Draft<NonNullable<S>>) => void | S) => void];
@bglgwyng bglgwyng changed the title Feature Request: Enhance useImmer's type [WIP] Feature Request: Enhance useImmer's type Jul 26, 2021
@bglgwyng bglgwyng changed the title [WIP] Feature Request: Enhance useImmer's type Feature Request: Enhance useImmer's type Jul 26, 2021
@mweststrate
Copy link
Collaborator

mweststrate commented Nov 19, 2022

NonNullable<S> makes a generic assumption which cannot be guaranteed, that would apply to all users of useImmer. Instead, I recommend to indeed make your code type safe by leveraging TS's inference, e.g. updateDog(draft => { if (draft) { / * draft will be infered to be non-nullable here */ }) is barely more verbose and actually type safe against programmer errors.

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

2 participants