Unknown type in Immutable object

52 views Asked by At

I am using Typescript 5.3.3 and I have reducer code that generates ts(2345) errors.

The reducer looks like this:

const initialState = Immutable.fromJS({
  isLoading: false,
})

const myReducer = (state = initialState, action) => {
  switch (action.type) {
    case 'LOAD':
      return state.set('isLoading', false)   <--- ERROR
    default: return state
  }
}

This version generates an error on the marked line:

Argument of type 'boolean' is not assignable to parameter of type 'Map<"valueOf", Map<never, never>> | Map<"valueOf", Map<never, never>>'.ts(2345)

I have tried introducing an interface like this:

interface State {
  isLoading: boolean
}

const initialState : State = Immutable.fromJS({   <--- ERROR 1
  isLoading: false,
})

const myReducer = (state: State = initialState, action) : State => {
  switch (action.type) {
    case 'LOAD':
      return state.set('isLoading', false)   <--- ERROR 2
    default: return state
  }
}

But that generates two errors as marked above:

  1. Property 'isLoading' is missing in type 'Map<"isLoading", Map<"valueOf", Map<never, never>>>' but required in type 'State'.ts(2741)
  2. Property 'set' does not exist on type 'State'.ts(2339)

The weird thing is that I have pretty much identical reducers (of the first type, i.e. with no interfaces) in other files where this works fine, so not sure why it doesn't work here.

Any ideas?

2

There are 2 answers

2
Arkin Solomon On

You are declaring initialState to be of type State. However, the value you are assigning to initialState is the return value of Immutable.fromJS(). This is the cause of your first error.

Your second error is caused since TypeScript expects state to be of type State. Since your State type only consists of the single property isLoading, state.set() is not found.

That being said, your initial code, works without error with TypeScript using [email protected] on Node 21.1 with TypeScript 5.2.2.

0
Jeff Mercado On

I suppose it would depend on how you import immutable. The problem appears to be that the initialState is not typed correctly. The call to fromJS() should be to the generic overload fromJS<JSValue>() which should return a correctly typed result. I don't know if you can do this with the state Immutable.fromJS() call. Try importing that instead.

i.e.,

import { fromJS } from 'immutable';
...
const initialState = fromJS({
  isLoading: false,
}); // may need to add `as const` to the arg to force the type