-
Notifications
You must be signed in to change notification settings - Fork 26.2k
feat(signal): better guardrails to avoid wrong signal object mutations #59287
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Hi @mauriziocescon 👋 I've proposed one of your solutions before there #58440.
Originally posted by @alxhub in #58440 So, @alxhub this topic comes up again ➿ I recommend something likt the ngrx signals has ngrx/platform#4526 by @rainerhahnekamp by default + a local/global flag to disable that behaving in dev mode for backward compatibility of all the existing codebases. |
@pawel-twardziak freezing can work without |
Yes, that's the approach in |
@alxhub - does this proposal add up? :) |
I've tried to do readonly for RxJS observables purely through TypeScript types for my project's codebase, but the problem is as soon as a function widens the type (i.e. from I would absolutely love Signals to do something like Object.freeze in dev mode. In my ideal world, Signals would return deep Readonly types and force specifying readonly types for function parameters - it's nice to have the compile time check that warns you that something's off, forcing you to clone to a new object or deep clone an array instead of mutating - but I understand why that would hinder Signal adoption. However, considering the amount of time new Angular developers waste chasing down why their object mutation doesn't kick off change detection and all of the non-obvious object mutation bugs I've had to chase down over the years, maybe that trade-off would be worth it. |
Fwiw, ngrx reverted their change to freeze the state (ngrx/platform#4686) |
Which @angular/* package(s) are relevant/related to the feature request?
core
Description
Hey!
I'm aware that the "not reactive" mutation of signal-objects is a known tradeoff (see for example #58440). Nevertheless, I wonder if there's really no way to mitigate the potential problems coming from it by throwing some sort of errors (at least at dev time).
Here is a minimal example:
https://stackblitz.com/edit/stackblitz-starters-bqez6f1y
A service acting as a store is just a popular use case, but essentially any signal having a (serialisable) object is potentially affected by the same problem. In all such cases, exposing / passing
computeds
orreadonly
signals don't make 100% sure the state cannot be accidentally mutated. At least, I'm not aware of any "ng-way" to achieve it.So I wonder: would be freezing / deepFreezing signals something the team has considered? For example as an opt-in in dev mode... as recently done by ngrx-store team. Alternatively, any other suggestion in userland to address the problem?
I understand this might favour a more "strictly immutable approach" to the data flow... and in general, it might make the signal implementation more complicated.
I hope I haven't missed anything trivial (in case sorry).
Thanks a lot!
Proposed solution
That I'm aware of:
read
/transform
/ ... option for signal / computed and cherry-pick the cases to freeze:const state = signal({ value: 0 }, {read: Object.freeze})
+ runtime errors,The text was updated successfully, but these errors were encountered: