One of the principles of React is that components are supposed to be pure - they shouldn't mutate the parameters they receive. If they do mutate parameters they receive they can mutate the state of a parent, or the state of the app.
We can now statically check mutation of objects by defining their type as DeepReadonly (source1, 2, 3). This could further be used for functions, by defining their parameters as DeepReadonly. I've started using it in my code and it works quite well. I get an error in the editor once I try to change a property of a parameter defined this way. It would be great if we can add this feature to the type of components (React.Compo ent and React.SFC). This can help keep state immutable, and components pure.
I'm not sure whom of the contributors I should mention, so I'll just mention every thrid contributor. @johnnyreilly @digiguru @DovydasNavickas @guilhermehubner @pascaloliv @Kovensky
@bbenezech @pzavolinsky @ericanderson @tkrotoff @onigoetz @theruther4d @ferdaber @jrakotoharisoa @hotell @franklixuefei @Kovensky @pshrmn
I haven't received any reply yet. Could you give it a thought? Many use 3rd libraries such as Immutable and Immer and special syntax to avoid mutation. I think DeepReadonly provides a better approach to achieve immutability in React. We don't need to replace the type of Component, but maybe add another type, which wraps state and props in DeepReadonly. If you think this is necessary I'd be happy to prepare a PR.
Oh, right, I need to update my username in the comments too.
ahem I should take a look tomorrow. I am totally in favor of deep
immutability of props and state but it won't actually do what we want until
TS3.4 (making Readonly
We already type the Component interface with Readonly<P> and Readonly<S> as their props and state instance properties, respectively, so it should be very easy to just change them to DeepReadonly instead.
but it won't actually do what we want until TS3.4 (making Readonly
actually become ReadonlyArray)
@Jessidhia , My experience is that if you use a properly defined DeepReadonly generic, mutating an array is not possible.
I prepared a small demo. https://stackblitz.com/edit/react-ts-klbbvc?file=RegularChild.tsx . RegularChild demonstrates the current situation, and DeepReadonlyChild demonstrates the proposal. In DeepReadonlyChild the editor shouts when we try to mutate nested fields, including nested arrays.
@bbenezech @pzavolinsky @ericanderson @tkrotoff @onigoetz @theruther4d @ferdaber @jrakotoharisoa @Hotell @franklixuefei @Kovensky @pshrmn @jessidhia
With the release of TS3.4, this should be doable now yes?
I have converted most of my components to a DeepReadonly form. It works well, and parameters or state could not be mutated. I plan to submit a PR later this week.
I submitted a PR yesterday. Please take a look.
https://github.com/DefinitelyTyped/DefinitelyTyped/pull/36066
Unfortunately, the new class component types suggested in #36066 won't prevent props from being mutated in the constructor.
I'm a bit confused about #36066. 7 days ago @ferdaber approved the suggested changes, but it hasn't been merged, and 1 hour ago Typescript-bot added the label "Abondoned". Can anyone explain?
@johnnyreilly @bbenezech @pzavolinsky @digiguru @ericanderson @DovydasNavickas @onigoetz @theruther4d @guilhermehubner @ferdaber @jrakotoharisoa @pascaloliv @Hotell @franklixuefei @Jessidhia @saranshkataria @lukyth @eps1lon
@carpben the builds were failing so it wasn't able to be merged.
@ferdaber ,
The error:

In VScode, after commenting all code suggested in this PR, still 40+ errors are found in that same style-component's file. Therefor I suspect this is not a result of the suggested code.

Any suggestion?
React is an insanely large typing library as far as dependencies go. Unfortunately not every update will be checked by the bot (of dependent libraries as well as the compiler itself), so often you'll get stuck with errors that appear over time in your PR that has to be fixed. I would suggest pinging the styled-components types authors for help here.
Most helpful comment
We already type the
Componentinterface withReadonly<P>andReadonly<S>as theirpropsandstateinstance properties, respectively, so it should be very easy to just change them toDeepReadonlyinstead.