3

Using typescript to modify an immutable state using the npm package 'immutability-helper' i'm facing some strange error (at least for now). I can set an object but not merge it. Can you clarify why?

Given the following data:

export enum NetworkState {
    Checking,
    UpdateAvailable,
    Downloading,
    UpdateDownloaded,
    UpToDate,
    Error
}

export class Update {
    public networkState: NetworkState = NetworkState.UpToDate;
    public progress: number = 1;
}

export class Updater {
    public client: Update = new Update();
    public games :Map<string, Update> = new Map<string, Update>();
}

My goal is to update the 'progress' value of a game's 'Update' object identified by his key 'gameKey'. Without immutability in mind the solution would be:

updateGameProgress(state: Updater, payload: {gameKey: string, progress: number}){
   state.games.get(payload.gameKey).progress = payload.progress
}

With immutability the solution i'm using is:

updateGameProgress(state: Updater, payload: {gameKey: string, progress: number}){
   update(state, {
        games: {
            [payload.gameKey]: {
                $set: {
                    networkState: state.games.get(payload.gameKey).networkState,
                    progress: payload.progress
                } 
            }
        }
    });
}

But i'm not satisfied with this solution because it forces me to provide a value for each member of the Update object. The Update only contains two properties so it's not a big deal but what if i have 10+ properties. Unfortunately, my attempts at using $merge where unsuccessfull. The following code generates a compilation error that didn't give me a clue about what was wrong.

updateGameProgress(state: Updater, payload: {gameKey: string, progress: number}){
   update(state, {
        games: {
            [payload.gameKey]: {
                $merge: {
                    progress: payload.progress
                } 
            }
        }
    });
}

Compilation error:

Argument of type '{ games: { [x: string]: { $merge: { progress: number; }; }; }; }' is not assignable to parameter of type 'Spec'. Type '{ games: { [x: string]: { $merge: { progress: number; }; }; }; }' is not assignable to type '{ client?: Spec; games?: Spec, never>; }'.
Types of property 'games' are incompatible. Type '{ [x: string]: { $merge: { progress: number; }; }; }' is not assignable to type 'Spec, never>'. Property '$apply' is missing in type '{ [x: string]: { $merge: { progress: number; }; }; }' but required in type '{ $apply: (v: Map) => Map; }'.

Can you clarify why this compilation error is generated ? And what could be a valid syntax to execute this merge ?

Thanks

Mumrah81
  • 2,034
  • 2
  • 16
  • 23
  • 1
    This appears to be a deficiency of `immutability-helper`: it simply doesn't support `$merge` inside a `Map`. Here's the type of map spec: https://github.com/kolodny/immutability-helper/blob/master/index.ts#L344 – Fyodor Soikin Jan 17 '20 at 16:44
  • @FyodorSoikin thanks for the link, it is a valuable resource – Mumrah81 Jan 17 '20 at 20:56

0 Answers0