Skip to content

A signal value returned by its getter should be of a readonly type #58440

@pawel-twardziak

Description

@pawel-twardziak

Which @angular/* package(s) are relevant/related to the feature request?

core

Description

Having a signal like this:

const config = signal({ options: { active: true, name: 'engine' } });

it is unfortunately possible to proceed this:

config().options.active = false

What a foully way.... 😆
This change is happening outside the graph which means no consumers will be notified about the change.

Changing the signal value like this is an abuse that can cause some pretty unexpected code behavior, to say the least.
This also kinda violates the immutability pattern.

Correct me if I am wrong, but I reckon that each signal value should be readonly in a deep manner.

Stackblitz playground

Proposed solution

I've digging around the code a bit and my proposal is quite simple. I am not sure about all possible consequences to the entire codebase.

export type SignalBaseGetter<T> = (() => ReadonlyDeep<T>) & {readonly [SIGNAL]: unknown};
export type ComputedGetter<T> = (() => ReadonlyDeep<T>) & {
  [SIGNAL]: ComputedNode<T>;
};

I've defined ReadonlyDeep type based on type-fest

Concluding, my commit is kinda ready - but yet again, I am totaly not sure about the impact.

Does it add up?

Alternatives considered

Keep it as it is - each dev should be aware of how to set/update a signal value properly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: coreIssues related to the framework runtimecore: reactivityWork related to fine-grained reactivity in the core frameworkcross-cutting: signals

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions