diff --git a/modules/signals/entities/src/models.ts b/modules/signals/entities/src/models.ts index a32f60fd06..1f89ad6c30 100644 --- a/modules/signals/entities/src/models.ts +++ b/modules/signals/entities/src/models.ts @@ -13,12 +13,12 @@ export type NamedEntityState = { [K in keyof EntityState as `${Collection}${Capitalize}`]: EntityState[K]; }; -export type EntitySignals = { +export type EntityComputed = { entities: Signal; }; -export type NamedEntitySignals = { - [K in keyof EntitySignals as `${Collection}${Capitalize}`]: EntitySignals[K]; +export type NamedEntityComputed = { + [K in keyof EntityComputed as `${Collection}${Capitalize}`]: EntityComputed[K]; }; export type EntityIdProps = { diff --git a/modules/signals/entities/src/with-entities.ts b/modules/signals/entities/src/with-entities.ts index 2e7c391b67..5962420d3c 100644 --- a/modules/signals/entities/src/with-entities.ts +++ b/modules/signals/entities/src/with-entities.ts @@ -6,20 +6,20 @@ import { withState, } from '@ngrx/signals'; import { + EntityComputed, EntityId, EntityMap, - EntitySignals, EntityState, - NamedEntitySignals, + NamedEntityComputed, NamedEntityState, } from './models'; import { getEntityStateKeys } from './helpers'; export function withEntities(): SignalStoreFeature< - { state: {}; signals: {}; methods: {} }, + { state: {}; computed: {}; methods: {} }, { state: EntityState; - signals: EntitySignals; + computed: EntityComputed; methods: {}; } >; @@ -27,20 +27,20 @@ export function withEntities(config: { entity: Entity; collection: Collection; }): SignalStoreFeature< - { state: {}; signals: {}; methods: {} }, + { state: {}; computed: {}; methods: {} }, { state: NamedEntityState; - signals: NamedEntitySignals; + computed: NamedEntityComputed; methods: {}; } >; export function withEntities(config: { entity: Entity; }): SignalStoreFeature< - { state: {}; signals: {}; methods: {} }, + { state: {}; computed: {}; methods: {} }, { state: EntityState; - signals: EntitySignals; + computed: EntityComputed; methods: {}; } >; diff --git a/modules/signals/spec/signal-store-feature.spec.ts b/modules/signals/spec/signal-store-feature.spec.ts index a8d8b8d4b1..f3dfd5998b 100644 --- a/modules/signals/spec/signal-store-feature.spec.ts +++ b/modules/signals/spec/signal-store-feature.spec.ts @@ -34,7 +34,7 @@ describe('signalStoreFeature', () => { return signalStoreFeature( { state: type<{ foo: string }>(), - signals: type<{ s: Signal }>(), + computed: type<{ s: Signal }>(), }, withState({ foo1: 1 }), withState({ foo2: 2 }) diff --git a/modules/signals/spec/types/signal-store.types.spec.ts b/modules/signals/spec/types/signal-store.types.spec.ts index 50ece43080..9a37586686 100644 --- a/modules/signals/spec/types/signal-store.types.spec.ts +++ b/modules/signals/spec/types/signal-store.types.spec.ts @@ -653,7 +653,7 @@ describe('signalStore', () => { return signalStoreFeature( { state: type<{ q1: string }>(), - signals: type<{ sig: Signal }>(), + computed: type<{ sig: Signal }>(), }, withState({ y: initialY }), withComputed(() => ({ sigY: computed(() => 'sigY') })), @@ -739,7 +739,7 @@ describe('signalStore', () => { ); const feature = signalStoreFeature( - { signals: type<{ sig: Signal }>() }, + { computed: type<{ sig: Signal }>() }, withX(), withState({ q1: 'q1' }), withY(), @@ -785,7 +785,7 @@ describe('signalStore', () => { ${baseSnippet} const feature = signalStoreFeature( - { signals: type<{ sig: Signal }>() }, + { computed: type<{ sig: Signal }>() }, withComputed(() => ({ sig: computed(() => 1) })), withX(), withState({ q1: 'q1' }), @@ -817,7 +817,7 @@ describe('signalStore', () => { ); const feature = signalStoreFeature( - { signals: type<{ sig: Signal }>() }, + { computed: type<{ sig: Signal }>() }, withComputed(() => ({ sig: computed(() => 1) })), withX(), withState({ q1: 'q1' }), @@ -860,7 +860,7 @@ describe('signalStore', () => { entities: Entity[]; selectedEntity: Entity | null; }; - signals: { + computed: { selectedEntity2: Signal; }; methods: { diff --git a/modules/signals/spec/with-computed.spec.ts b/modules/signals/spec/with-computed.spec.ts index 08b4bff011..106516d396 100644 --- a/modules/signals/spec/with-computed.spec.ts +++ b/modules/signals/spec/with-computed.spec.ts @@ -3,7 +3,7 @@ import { withComputed, withMethods, withState } from '../src'; import { getInitialInnerStore } from '../src/signal-store'; describe('withComputed', () => { - it('adds signals to the store immutably', () => { + it('adds computed signals to the store immutably', () => { const initialStore = getInitialInnerStore(); const s1 = signal('s1').asReadonly(); @@ -11,14 +11,14 @@ describe('withComputed', () => { const store = withComputed(() => ({ s1, s2 }))(initialStore); - expect(Object.keys(store.signals)).toEqual(['s1', 's2']); - expect(Object.keys(initialStore.signals)).toEqual([]); + expect(Object.keys(store.computedSignals)).toEqual(['s1', 's2']); + expect(Object.keys(initialStore.computedSignals)).toEqual([]); - expect(store.signals.s1).toBe(s1); - expect(store.signals.s2).toBe(s2); + expect(store.computedSignals.s1).toBe(s1); + expect(store.computedSignals.s2).toBe(s2); }); - it('overrides previously defined slices, signals, and methods with the same name', () => { + it('overrides previously defined state signals, computed signals, and methods with the same name', () => { const initialStore = [ withState({ p1: 10, @@ -42,10 +42,16 @@ describe('withComputed', () => { s3: signal({ s: 3 }).asReadonly(), }))(initialStore); - expect(Object.keys(store.signals)).toEqual(['s1', 's2', 'p1', 'm1', 's3']); - expect(store.signals.s2).toBe(s2); + expect(Object.keys(store.computedSignals)).toEqual([ + 's1', + 's2', + 'p1', + 'm1', + 's3', + ]); + expect(store.computedSignals.s2).toBe(s2); - expect(Object.keys(store.slices)).toEqual(['p2']); + expect(Object.keys(store.stateSignals)).toEqual(['p2']); expect(Object.keys(store.methods)).toEqual(['m2']); }); }); diff --git a/modules/signals/spec/with-methods.spec.ts b/modules/signals/spec/with-methods.spec.ts index ab78798e46..3e6e59309f 100644 --- a/modules/signals/spec/with-methods.spec.ts +++ b/modules/signals/spec/with-methods.spec.ts @@ -18,7 +18,7 @@ describe('withMethods', () => { expect(store.methods.m2).toBe(m2); }); - it('overrides previously defined slices, signals, and methods with the same name', () => { + it('overrides previously defined state signals, computed signals, and methods with the same name', () => { const initialStore = [ withState({ p1: 'p1', @@ -45,7 +45,7 @@ describe('withMethods', () => { expect(Object.keys(store.methods)).toEqual(['m1', 'm2', 'p2', 's1', 'm3']); expect(store.methods.m2).toBe(m2); - expect(Object.keys(store.slices)).toEqual(['p1']); - expect(Object.keys(store.signals)).toEqual(['s2']); + expect(Object.keys(store.stateSignals)).toEqual(['p1']); + expect(Object.keys(store.computedSignals)).toEqual(['s2']); }); }); diff --git a/modules/signals/spec/with-state.spec.ts b/modules/signals/spec/with-state.spec.ts index 0a07b82c6f..bccc702ea9 100644 --- a/modules/signals/spec/with-state.spec.ts +++ b/modules/signals/spec/with-state.spec.ts @@ -17,8 +17,8 @@ describe('withState', () => { expect(state).toEqual({ foo: 'bar', x: { y: 'z' } }); expect(initialState).toEqual({}); - expect(Object.keys(store.slices)).toEqual(['foo', 'x']); - expect(Object.keys(initialStore.slices)).toEqual([]); + expect(Object.keys(store.stateSignals)).toEqual(['foo', 'x']); + expect(Object.keys(initialStore.stateSignals)).toEqual([]); }); it('creates deep signals for each state slice', () => { @@ -29,14 +29,14 @@ describe('withState', () => { x: { y: 'z' }, })(initialStore); - expect(store.slices.foo()).toBe('bar'); - expect(isSignal(store.slices.foo)).toBe(true); + expect(store.stateSignals.foo()).toBe('bar'); + expect(isSignal(store.stateSignals.foo)).toBe(true); - expect(store.slices.x()).toEqual({ y: 'z' }); - expect(isSignal(store.slices.x)).toBe(true); + expect(store.stateSignals.x()).toEqual({ y: 'z' }); + expect(isSignal(store.stateSignals.x)).toBe(true); - expect(store.slices.x.y()).toBe('z'); - expect(isSignal(store.slices.x.y)).toBe(true); + expect(store.stateSignals.x.y()).toBe('z'); + expect(isSignal(store.stateSignals.x.y)).toBe(true); }); it('patches state signal and creates deep signals for state slices provided via factory', () => { @@ -49,12 +49,12 @@ describe('withState', () => { const state = store[STATE_SIGNAL](); expect(state).toEqual({ foo: 'bar', x: { y: 'z' } }); - expect(store.slices.foo()).toBe('bar'); - expect(store.slices.x()).toEqual({ y: 'z' }); - expect(store.slices.x.y()).toBe('z'); + expect(store.stateSignals.foo()).toBe('bar'); + expect(store.stateSignals.x()).toEqual({ y: 'z' }); + expect(store.stateSignals.x.y()).toBe('z'); }); - it('overrides previously defined state slices, signals, and methods with the same name', () => { + it('overrides previously defined state signals, computed signals, and methods with the same name', () => { const initialStore = [ withState({ p1: 10, @@ -77,10 +77,16 @@ describe('withState', () => { p3: 'p3', }))(initialStore); - expect(Object.keys(store.slices)).toEqual(['p1', 'p2', 's2', 'm2', 'p3']); - expect(store.slices.p2()).toBe(100); + expect(Object.keys(store.stateSignals)).toEqual([ + 'p1', + 'p2', + 's2', + 'm2', + 'p3', + ]); + expect(store.stateSignals.p2()).toBe(100); - expect(Object.keys(store.signals)).toEqual(['s1']); + expect(Object.keys(store.computedSignals)).toEqual(['s1']); expect(Object.keys(store.methods)).toEqual(['m1']); }); }); diff --git a/modules/signals/src/signal-store-models.ts b/modules/signals/src/signal-store-models.ts index 98229c91f2..32486c1748 100644 --- a/modules/signals/src/signal-store-models.ts +++ b/modules/signals/src/signal-store-models.ts @@ -5,9 +5,7 @@ import { IsKnownRecord, Prettify } from './ts-helpers'; export type SignalStoreConfig = { providedIn: 'root' }; -export type SignalStoreSlices = IsKnownRecord< - Prettify -> extends true +export type StateSignals = IsKnownRecord> extends true ? { [Key in keyof State]: IsKnownRecord extends true ? DeepSignal @@ -17,8 +15,8 @@ export type SignalStoreSlices = IsKnownRecord< export type SignalStoreProps = Prettify< - SignalStoreSlices & - FeatureResult['signals'] & + StateSignals & + FeatureResult['computed'] & FeatureResult['methods'] >; @@ -33,29 +31,29 @@ export type SignalStoreHooks = { export type InnerSignalStore< State extends object = object, - Signals extends SignalsDictionary = SignalsDictionary, + ComputedSignals extends SignalsDictionary = SignalsDictionary, Methods extends MethodsDictionary = MethodsDictionary > = { - slices: SignalStoreSlices; - signals: Signals; + stateSignals: StateSignals; + computedSignals: ComputedSignals; methods: Methods; hooks: SignalStoreHooks; } & StateSignal; export type SignalStoreFeatureResult = { state: object; - signals: SignalsDictionary; + computed: SignalsDictionary; methods: MethodsDictionary; }; -export type EmptyFeatureResult = { state: {}; signals: {}; methods: {} }; +export type EmptyFeatureResult = { state: {}; computed: {}; methods: {} }; export type SignalStoreFeature< Input extends SignalStoreFeatureResult = SignalStoreFeatureResult, Output extends SignalStoreFeatureResult = SignalStoreFeatureResult > = ( - store: InnerSignalStore -) => InnerSignalStore; + store: InnerSignalStore +) => InnerSignalStore; export type MergeFeatureResults< FeatureResults extends SignalStoreFeatureResult[] @@ -78,7 +76,7 @@ export type MergeFeatureResults< type FeatureResultKeys = | keyof FeatureResult['state'] - | keyof FeatureResult['signals'] + | keyof FeatureResult['computed'] | keyof FeatureResult['methods']; type MergeTwoFeatureResults< @@ -86,6 +84,6 @@ type MergeTwoFeatureResults< Second extends SignalStoreFeatureResult > = { state: Omit>; - signals: Omit>; + computed: Omit>; methods: Omit>; } & Second; diff --git a/modules/signals/src/signal-store.ts b/modules/signals/src/signal-store.ts index 56c83d38a9..fdfccad04e 100644 --- a/modules/signals/src/signal-store.ts +++ b/modules/signals/src/signal-store.ts @@ -308,8 +308,8 @@ export function signalStore( (store, feature) => feature(store), getInitialInnerStore() ); - const { slices, signals, methods, hooks } = innerStore; - const props = { ...slices, ...signals, ...methods }; + const { stateSignals, computedSignals, methods, hooks } = innerStore; + const props = { ...stateSignals, ...computedSignals, ...methods }; (this as any)[STATE_SIGNAL] = innerStore[STATE_SIGNAL]; @@ -335,8 +335,8 @@ export function signalStore( export function getInitialInnerStore(): InnerSignalStore { return { [STATE_SIGNAL]: signal({}), - slices: {}, - signals: {}, + stateSignals: {}, + computedSignals: {}, methods: {}, hooks: {}, }; diff --git a/modules/signals/src/with-computed.ts b/modules/signals/src/with-computed.ts index a0df8f916c..0245c8363f 100644 --- a/modules/signals/src/with-computed.ts +++ b/modules/signals/src/with-computed.ts @@ -5,29 +5,35 @@ import { SignalsDictionary, SignalStoreFeature, SignalStoreFeatureResult, - SignalStoreSlices, + StateSignals, } from './signal-store-models'; import { Prettify } from './ts-helpers'; export function withComputed< Input extends SignalStoreFeatureResult, - Signals extends SignalsDictionary + ComputedSignals extends SignalsDictionary >( signalsFactory: ( - store: Prettify & Input['signals']> - ) => Signals -): SignalStoreFeature { + store: Prettify & Input['computed']> + ) => ComputedSignals +): SignalStoreFeature< + Input, + EmptyFeatureResult & { computed: ComputedSignals } +> { return (store) => { - const signals = signalsFactory({ ...store.slices, ...store.signals }); - const signalsKeys = Object.keys(signals); - const slices = excludeKeys(store.slices, signalsKeys); - const methods = excludeKeys(store.methods, signalsKeys); + const computedSignals = signalsFactory({ + ...store.stateSignals, + ...store.computedSignals, + }); + const computedSignalsKeys = Object.keys(computedSignals); + const stateSignals = excludeKeys(store.stateSignals, computedSignalsKeys); + const methods = excludeKeys(store.methods, computedSignalsKeys); return { ...store, - slices, - signals: { ...store.signals, ...signals }, + stateSignals, + computedSignals: { ...store.computedSignals, ...computedSignals }, methods, - } as InnerSignalStore, Signals>; + } as InnerSignalStore, ComputedSignals>; }; } diff --git a/modules/signals/src/with-hooks.ts b/modules/signals/src/with-hooks.ts index df8c65d5dc..af7fbeb5d3 100644 --- a/modules/signals/src/with-hooks.ts +++ b/modules/signals/src/with-hooks.ts @@ -3,14 +3,14 @@ import { EmptyFeatureResult, SignalStoreFeature, SignalStoreFeatureResult, - SignalStoreSlices, + StateSignals, } from './signal-store-models'; import { Prettify } from './ts-helpers'; type HookFn = ( store: Prettify< - SignalStoreSlices & - Input['signals'] & + StateSignals & + Input['computed'] & Input['methods'] & StateSignal> > @@ -18,8 +18,8 @@ type HookFn = ( type HooksFactory = ( store: Prettify< - SignalStoreSlices & - Input['signals'] & + StateSignals & + Input['computed'] & Input['methods'] & StateSignal> > @@ -47,8 +47,8 @@ export function withHooks( return (store) => { const storeProps = { [STATE_SIGNAL]: store[STATE_SIGNAL], - ...store.slices, - ...store.signals, + ...store.stateSignals, + ...store.computedSignals, ...store.methods, }; const hooks = diff --git a/modules/signals/src/with-methods.ts b/modules/signals/src/with-methods.ts index 3c54e8a346..e96741e40a 100644 --- a/modules/signals/src/with-methods.ts +++ b/modules/signals/src/with-methods.ts @@ -7,7 +7,7 @@ import { SignalsDictionary, SignalStoreFeature, SignalStoreFeatureResult, - SignalStoreSlices, + StateSignals, } from './signal-store-models'; import { Prettify } from './ts-helpers'; @@ -17,8 +17,8 @@ export function withMethods< >( methodsFactory: ( store: Prettify< - SignalStoreSlices & - Input['signals'] & + StateSignals & + Input['computed'] & Input['methods'] & StateSignal> > @@ -27,18 +27,18 @@ export function withMethods< return (store) => { const methods = methodsFactory({ [STATE_SIGNAL]: store[STATE_SIGNAL], - ...store.slices, - ...store.signals, + ...store.stateSignals, + ...store.computedSignals, ...store.methods, }); const methodsKeys = Object.keys(methods); - const slices = excludeKeys(store.slices, methodsKeys); - const signals = excludeKeys(store.signals, methodsKeys); + const stateSignals = excludeKeys(store.stateSignals, methodsKeys); + const computedSignals = excludeKeys(store.computedSignals, methodsKeys); return { ...store, - slices, - signals, + stateSignals, + computedSignals, methods: { ...store.methods, ...methods }, } as InnerSignalStore, SignalsDictionary, Methods>; }; diff --git a/modules/signals/src/with-state.ts b/modules/signals/src/with-state.ts index c36af79989..64c26c73b3 100644 --- a/modules/signals/src/with-state.ts +++ b/modules/signals/src/with-state.ts @@ -38,19 +38,19 @@ export function withState( ...state, })); - const slices = stateKeys.reduce((acc, key) => { - const slice = computed( + const stateSignals = stateKeys.reduce((acc, key) => { + const sliceSignal = computed( () => (store[STATE_SIGNAL]() as Record)[key] ); - return { ...acc, [key]: toDeepSignal(slice) }; + return { ...acc, [key]: toDeepSignal(sliceSignal) }; }, {} as SignalsDictionary); - const signals = excludeKeys(store.signals, stateKeys); + const computedSignals = excludeKeys(store.computedSignals, stateKeys); const methods = excludeKeys(store.methods, stateKeys); return { ...store, - slices: { ...store.slices, ...slices }, - signals, + stateSignals: { ...store.stateSignals, ...stateSignals }, + computedSignals, methods, } as InnerSignalStore; }; diff --git a/projects/ngrx.io/content/guide/signals/signal-store/custom-store-features.md b/projects/ngrx.io/content/guide/signals/signal-store/custom-store-features.md index 9db3e6917f..44fa80da79 100644 --- a/projects/ngrx.io/content/guide/signals/signal-store/custom-store-features.md +++ b/projects/ngrx.io/content/guide/signals/signal-store/custom-store-features.md @@ -244,13 +244,13 @@ In addition to state, it's also possible to define expected computed properties -import { computed, Signal } from '@angular/core'; -import { signalStoreFeature, type, withComputed, withHooks } from '@ngrx/signals'; +import { Signal } from '@angular/core'; +import { signalStoreFeature, type, withMethods } from '@ngrx/signals'; export function withBaz() { return signalStoreFeature( { - signals: type<{ foo: Signal<number> }>(), + computed: type<{ foo: Signal<number> }>(), methods: type<{ bar(): void }>(), }, withMethods(({ foo, bar }) => ({