Victor Ivens
Victor Ivens

Reputation: 2279

How to use Immer with Typescript

I'm trying to use Immer with my react project which is already using Typescript. I couldn't find in the docs, or anywhere else, how to actually use immer with typescript.

What I have so far:

export interface IProps { }

export interface IState {
  names: string[]
}

export class ListNames extends React.Component<IProps, IState> {
  constructor(props: IProps) {
    super(props)
    this.state = { names: [] }
  }

  addName = (name: string) => {
    this.setState(produce(draftState => {
      draftState.names.push(name)
    }))
  }
  ...
}

this gives me two errors:

  1. [ts] Object is possibly 'null'
  2. [ts] Property 'names' does not exist on type 'DraftObject<Pick<IState, never>>'

enter image description here

Setting the type for draftState to IState won't work. What I've done that made it work was to cast the draftState to IState before I use it.

enter image description here

The thing is: I might want to use draftState more than one time, so it is at least inconvenient.

What's the correct way to use Immer with Typescript?

Upvotes: 7

Views: 11521

Answers (1)

Explosion Pills
Explosion Pills

Reputation: 191729

Looking at the type definition for produce, it takes a generic type that is the state which defaults to any. Your TypeScript rules are set up in such a way that it thinks draftState could be null. You can specify the generic type to produce to specify what the state is:

produce<IState>(draftObject ...

Upvotes: 11

Related Questions