Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can TypeScript's `readonly` fully replace Immutable.js?

I have worked on a couple of projects using React.js. Some of them have used Flux, some Redux and some were just plain React apps utilizing Context.

I really like the way how Redux is using functional patterns. However, there is a strong chance that developers unintentionally mutate the state. When searching for a solution, there is basically just one answer - Immutable.js. To be honest, I hate this library. It totally changes the way you use JavaScript. Moreover, it has to be implemented throughout the whole application, otherwise you end up having weird errors when some objects are plain JS and some are Immutable structures. Or you start using .toJS(), which is - again - very very bad.

Recently, a colleague of mine has suggested using TypeScript. Aside from the type safety, it has one interesting feature - you can define your own data structures, which have all their fields labeled as readonly. Such a structure would be essentially immutable.

I am not an expert on either Immutable.js or TypeScript. However, the promise of having immutable data structures inside Redux store and without using Immutable.js seems too good to be true. Is TypeScript's readonly a suitable replacement for Immutable.js? Or are there any hidden issues?

like image 926
Storm Avatar asked Apr 29 '19 14:04

Storm


People also ask

When should I use readonly TypeScript?

TypeScript - ReadOnly Prefix readonly is used to make a property as read-only. Read-only members can be accessed outside the class, but their value cannot be changed.

Do you need immutable JS?

Using ImmutableJS can improve dramatically the performance of your application. And, because the immutable data never changes, you can always expect new data to be passed from the above. To make sure you are correctly comparing the data and not updating the UI when there is no change, you should always use the .

Why should we use immutable JS?

Immutable. js is a library that supports an immutable data structure. It means that once created data cannot be changed. It makes maintaining immutable data structures easier and more efficient.

Is VAR immutable in JavaScript?

var and let are reassignable values, while const has limited mutability. var and let can be reassigned - which is the act of setting a value at one point in time, and then using the same variable reference and giving it a new value.


1 Answers

While it is true that the readonly modifier of TypeScript only exists at design type and does not affect runtime code, this is true of the entire type system. That is, nothing stops you at runtime from assigning a number to a variable of type string. So that answer is kind of a red herring... if you get warned at design time that you're trying to mutate something marked as const or readonly, then that would possibly eliminate the need for extensive runtime checking.

But there is a major reason why readonly is insufficient. There is an outstanding issue with readonly, which is that currently (as of TS3.4), types that differ only in their readonly attributes are mutually assignable. Which lets you easily bust through the protective readonly shell of any property and mess with the innards:

type Person = { name: string, age: number }
type ReadonlyPerson = Readonly<Person>;

const readonlyPerson: ReadonlyPerson = { name: "Peter Pan", age: 12 };
readonlyPerson.age = 40; // error, "I won't grow up!"

const writablePerson: Person = readonlyPerson; // no error?!?!
writablePerson.age = 40; // no error!  Get a job, Peter.

console.log(readonlyPerson.age); // 40

This is pretty bad for readonly. Until that gets resolved, you might find yourself agreeing with a previous issue filer who had originally named the issue "readonly modifiers are a joke" 🤡.

Even if this does get resolved, readonly might not cover all use cases. You'd also need to walk through all interfaces and types in your libraries (or even the standard libraries) and remove methods that mutate state. So all uses of Array would need to be changed to ReadonlyArray and all uses of Map would need to be changed to ReadonlyMap, etc. Once you did this you'd have a fairly typesafe way to represent immutability. But it's a lot of work.

Anyway, hope that helps; good luck!

like image 180
jcalz Avatar answered Sep 28 '22 17:09

jcalz