platform icon indicating copy to clipboard operation
platform copied to clipboard

Enhance DeepSignal and toDeepSignal to support arrays

Open samuelfernandez opened this issue 1 year ago • 2 comments

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

signals

Information

Right now deep signals only support record-like signals. Ideally it would also support array-like structures, providing the same “deep” behavior.

It would be more tricky, since it’d need to proxy mutation operations, but should be technically possible.

Describe any alternatives/workarounds you're currently using

No response

I would be willing to submit a PR to fix this issue

  • [ ] Yes
  • [X] No

samuelfernandez avatar Oct 12 '24 14:10 samuelfernandez

Can you provide an example of how the usage of arrays with deep signals within the SignalStore/State should look like? How the state update would look like?

markostanimirovic avatar Oct 14 '24 19:10 markostanimirovic

Can you provide an example of how the usage of arrays with deep signals within the SignalStore/State should look like? How the state update would look like?

@markostanimirovic Sure! Doing a quick comparison with records. When T extends a record:

type DeepSignal<T extends Record<any,any>> = Signal<T> & { [K in keyof T]: DeepSignal<T[K]> };

interface Person {
  name: string;
}

const deepPersonSignal: DeepSignal<Person> = /**/;

deepPersonSignal(); // Type: Person, emits reactively the person object.
deepPersonSignal.name(); // Type: string, signal that emits reactively the name.

My proposal, when the generic is an array, would be having this:

type DeepSignal<T extends R[]> = Signal<R[]> & { [K in keyof T]: DeepSignal<T[K]> } & {
  length: Signal<number>,
  entries: Signal<IterableIterator<[number, R]>>,
  keys: Signal<IterableIterator<number>>,
  values: Signal<IterableIterator<R>>
};

const deepPersonsSignal: DeepSignal<Person[]> = /**/;

deepPersonsSignal(); // Type: Person[], emits reactively the person array.
deepPersonsSignal[0](); // Type: Person, signal that emits reactively the first element of the array.
deepPersonsSignal[0].name(); // Type: string, signal that emits reactively the name of the first element.

Connecting to @alxhub's comment here: https://github.com/ducin/sygnalyze/issues/1#issuecomment-1954916055

It'd be ideal that the deep signal of arrays didn't emit if only values are updated, but the array length is the same. As pointed out by @alxhub it would enhance the performance of @for control flow.

samuelfernandez avatar Oct 18 '24 14:10 samuelfernandez