From 5d2572ed5105053cf3b5ecfdf704872c106a11c2 Mon Sep 17 00:00:00 2001 From: Rainer Hahnekamp Date: Sat, 23 Nov 2024 00:34:43 +0100 Subject: [PATCH] fix!: exclude class instance from `DeepSignal` This is a draft. `IsRecord` tries to differentiate a class instance from object literal by checking if a prototype is there or not. It kind of works but breaks a lot of other functions depending on it. --- .../spec/types/signal-state.types.spec.ts | 16 +++++++++ modules/signals/src/ts-helpers.ts | 33 ++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/modules/signals/spec/types/signal-state.types.spec.ts b/modules/signals/spec/types/signal-state.types.spec.ts index c9edeab141..2d7e1cdfb1 100644 --- a/modules/signals/spec/types/signal-state.types.spec.ts +++ b/modules/signals/spec/types/signal-state.types.spec.ts @@ -160,6 +160,22 @@ describe('signalState', () => { ); }); + it('does not create deep signals for a class instance', () => { + const snippet = ` + class User { + id = 0; + name = 'Konrad'; + } + + const state = signalState({ user: new User() }); + const user = state.user; + `; + + expectSnippet(snippet).toSucceed(); + + expectSnippet(snippet).toInfer('user', 'Signal'); + }); + it('does not create deep signals for optional state slices', () => { const snippet = ` type State = { diff --git a/modules/signals/src/ts-helpers.ts b/modules/signals/src/ts-helpers.ts index f7df5cdb77..69b1a66473 100644 --- a/modules/signals/src/ts-helpers.ts +++ b/modules/signals/src/ts-helpers.ts @@ -1,3 +1,6 @@ +import { Signal } from '@angular/core'; +import { signalState } from './signal-state'; + export type Prettify = { [K in keyof T]: T[K] } & {}; export type IsRecord = T extends object @@ -9,7 +12,11 @@ export type IsRecord = T extends object ? false : T extends Function ? false - : true + : T extends { prototype: unknown } // check for constructor did not work + ? false + : T extends { [key: string]: unknown } + ? true + : false : false; export type IsUnknownRecord = string extends keyof T @@ -27,3 +34,27 @@ export type IsKnownRecord = IsRecord extends true export type OmitPrivate = { [K in keyof T as K extends `_${string}` ? never : K]: T[K]; }; + +class User { + id = 0; + name = 'Konrad'; +} + +const state = { + user: new User(), + id: 1, + address: { city: 'Wien', zip: '1040' }, +}; + +type AssertFalse = T; +type AssertTrue = T; + +type T1 = AssertFalse>; +type T2 = AssertFalse>; +type T3 = AssertTrue>; + +const store = signalState(state); +const address: Signal<{ city: string; zip: string }> = store.address; +const user: Signal = store.user; +const zip: Signal = store.address.zip; +const id: Signal = store.id;