1

I want to edit original object data without mutation and possibly without deep cloning the original object. I found Immer. Using its produce function works just fine. But when I want to delete original object property I get an error The operand of a 'delete' operator must be optional. which is understandable.

interface User {
  name: string;
  surname: string;
  age: number;
}

const user: User = {
  name: 'John',
  surname: 'Small',
  age: 20
}

const changedUser = produce(user, (draft) => {
  draft.name = 'Mark';
  delete draft.age; // The operand of a 'delete' operator must be optional.
})

I can force its Base type like produce<Partial<User>>(/* ... */) but I think it's ugly and if you would like to edit nested objects, you would have to sanitize possible undefined errors. Are there any more suitable approaches?

tprieboj
  • 1,680
  • 6
  • 31
  • 54

1 Answers1

1

You need to think about where you are using your User and whether that usage is expecting to always have a complete User object. When you delete age from the user variable, changedUser is, by definition, not a User. So if you need a User then you should not do this.

If your code is ok with having an incomplete User object, then in my opinion you should be declaring that higher-up rather than on the produce function. When you create "John", make the type const user: Partial<User> = ....

I imagine that your actual code is more complex than this. So the place to introduce the Partial type is in the type definition for whatever state object you are altering with the produce.

With regards to making nested properties optional, you can use a utility type for that.

Linda Paiste
  • 38,446
  • 6
  • 64
  • 102