0

Specifically, how do I define an immutable data structure. For example, I want to define:

const user = {userName: 'user name', password: 'password'}

Such that everywhere it is used or accessed in code:

  • You cannot change a key
  • You cannot add or delete a key
  • You can only change the value associated to that key

The method of defining an immutable data structure should allow for nesting as well so that this structure is also immutable:

const user = {userName: 'user name', password: 'password', permissions: ['login', 'admin'], preferences: {favoriteColor: 'blue'} }

Why would anyone want to do this? Well, it's pretty standard in typing systems and we have real problems with data models in our JS code... we can only see the state via console.log and the structure is mutated all over the place, so devs can never see what should be a super static model and the form data becomes a mess.

Ultimately, how does one define immutable structure one way or another.

I tried everything, nothing seems to provide this need without perhaps typescript?

gunslingor
  • 1,358
  • 12
  • 34
  • 2
    [Object.freeze()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze), https://immutable-js.com or simply by convention (don't mutate objects you don't own. – Thomas Mar 14 '23 at 18:53
  • Thanks but it fails condition 3 since you can't change values associated to keys. – gunslingor Mar 14 '23 at 18:55
  • Maybe you should be using TypeScript... – kelsny Mar 14 '23 at 18:57
  • 1
    @gunslingor Then that's not immutable; and you should take a look at [Object.seal()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/seal) – Thomas Mar 14 '23 at 18:57
  • 1
    Ideally we should be using TypeScript to have static type checking, but yes, `Object.seal` (more specifically, an answer to this question would need a recursive `Object.seal`). – kelsny Mar 14 '23 at 19:00
  • 2
    *"You can only change the value associated to that key"*: that's what we call a mutation. – trincot Mar 14 '23 at 19:07
  • "*we can only see the state via console.log and the structure is mutated all over the place*" note that if that's the problem than what you ask for *does not solve it*. If you already have problem with haphazard mutations, then it's going to still be there if you allow property updates. Consider `const obj = { foo: 1}; console.log(obj); obj.foo = 2;` which will log the object, *then change the value* and thus when you expand the logged object, you'd see `2` instead of `1`. [See here](https://stackoverflow.com/q/11284663) – VLAZ Mar 14 '23 at 19:08
  • "*the structure is mutated all over the place, so devs can never see what should be a super static model*" this right there is your problem. Apparently, the code you have keeps mutating stuff. Whereas your developers apparently don't want to do that. In the exceptionally vast majority of cases, objects don't just get mutated without somebody from your team writing code to do it. So, most likely, your team has added code that mutates what it shouldn't. If the problem is, say, a library then most likely you'd get errors when the library tries that again with an immutable object. – VLAZ Mar 14 '23 at 19:15
  • @Thomas: To clarify, you are right, from JS perspective what I want is mutable... but from a data structures perspective, I only want "immutable structure"... i.e. another solution might be a class but its less obvious than JSON or ORM and could have a nesting issue. – gunslingor Mar 14 '23 at 19:24
  • @VLAZ: it would solve the problem by forcing the structure to be defined manually in code so we can see it in place. Regarding the mutations after declaration, most frontend frameworks allow it but its turned into a mess IMHO. Define structure, modify values is the solution in every framework or language I've used. – gunslingor Mar 14 '23 at 19:24
  • @vr. Thank you, that is the solution, perfect, I knew JS had to have something for this! And yes, I think typescript would also be a valid solution (recommend providing sample structure if you choose to answer with that). – gunslingor Mar 14 '23 at 19:25
  • @gunslingor The best part about using TypeScript here is that literally no changes are necessary (copy and paste to a TS file and it'll work). TypeScript will make sure you don't write code that changes the structure of the object. That's why I think you should be using TypeScript anyways. – kelsny Mar 14 '23 at 19:28
  • Without TypeScript, then even if you seal objects recursively, you still need code to forbid an assignment with an *object* as value -- only (some type of?) primitive values should be allowed as otherwise you still modify the structure. – trincot Mar 14 '23 at 19:44
  • Yeah, I think your totally write on typescript. We are building a new app soon with nextjs. I think my issue vanishes, this is just a question I've been struggling with, how to solve it in the old app... you guys are right, probably more trouble than it's worth... adding TS to the old project might be the right call. – gunslingor Mar 16 '23 at 21:02

0 Answers0