1

I recently update my project from Typescript 3.5 to 3.8. Everything run smoothly expect some operation on array.

    const usedROI = this.rois.find((roi) => roi.id === roiId);
    usedROI.position.height = position.height;

ERROR TypeError: Cannot assign to read only property 'height' of object '[object Object]'

   let rerouteWaypoint = route.waypoints.filter((wp) => wp.type === IWaypointType.REROUTE_POINT);
   rerouteWaypoint.forEach((wp) => (wp.type = IWaypointType.USER_POINT));

ERROR TypeError: Cannot assign to read only property 'type' of object '[object Array]'

  const wps = state.entities[action.payload.routeId].waypoints;
  const wp = {
    ...wps[index],
    ...action.payload.changes,
  };
  wps[index] = { ...wp }; <= this line breaks

core.js:4117 ERROR TypeError: Cannot assign to read only property '0' of object '[object Array]'

I do not use readonly anywhere in my app, it looks like all my array are frozen and uneditable.

Why so ? I do not see it in the breaking changes. Is there a way to find in visual code ALL the spot where this problem occur ? cause right now only the error pop at runtime and it's really unsafe to deploy such a version.

EDIT : Someone talk about a similar problem here => Error while sorting array of objects Cannot assign to read only property '2' of object '[object Array]'

but I do not see why simple array are also throwing it without beeing redux stored elements.

Bobby
  • 4,372
  • 8
  • 47
  • 103
  • 1
    Since this is a runtime error, not a compile-time error, it sounds like this relates to something *else* you updated at the same time as updating TypeScript. Something you're getting objects from has sealed or frozen the objects where it didn't used to (probably because they were always supposed to be read-only but earlier versions of whatever it is didn't enforce that). – T.J. Crowder May 28 '20 at 12:18
  • 1
    *"Is there a way to find in visual code ALL the spot where this problem occur ?"* Yes. Once you know what objects are sealed or frozen, you can update the type information you're using for them to say that their properties are read-only. Then TypeScript will catch anywhere you're assigning to them. (Provided you're not using type assertions or `any`, etc., to opt out of TypeScript's typing in places.) – T.J. Crowder May 28 '20 at 12:20
  • I will looks into this thanks – Bobby May 28 '20 at 12:22
  • It looks like everything that throw error is somewhat connected to ngrx, like value I get from selectors. but there is not way to type them as readonly – Bobby May 28 '20 at 12:24
  • All due respect, and recognizing that I haven't used it, based on the website, there's bound to be a way. – T.J. Crowder May 28 '20 at 12:25
  • You mentioned it is NGRX, didn't you? In that case, the state object is `readonly`, thus you shouldn't be directly mutating it.. – wentjun May 28 '20 at 12:31
  • 1
    @T.J.Crowder I found out, thanks for the help – Bobby May 28 '20 at 13:09

1 Answers1

1

Following @T.J.Crowder comment, I looked into my code and by default, if not typing a selector in NGRX, the returned value is NOT typed readonly.

I went trought all my selector and typed them appropriately for ex.

export const getSelectedProjectId = (state: State): Readonly<number> => state.selectedProjectId;
export const getError = (state: State): Readonly<string> => state.error;
export const getIsLoading = (state: State): Readonly<boolean> => state.isLoading;

export const selectAll: (state: object) => ReadonlyArray<IProject> = featureAdapter.getSelectors(selectProjectState).selectAll;
export const selectAllEntities: (state: object) => Dictionary<IProject> = featureAdapter.getSelectors(
  selectProjectState
).selectEntities;

This triggered ALL the error in typescript everywhere, and I then fixed them and fixed the project.

Community
  • 1
  • 1
Bobby
  • 4,372
  • 8
  • 47
  • 103