diff --git a/modules/signals/entities/spec/types/entity-config.types.spec.ts b/modules/signals/entities/spec/types/entity-config.types.spec.ts index f296ff8fcc..daf82fb958 100644 --- a/modules/signals/entities/spec/types/entity-config.types.spec.ts +++ b/modules/signals/entities/spec/types/entity-config.types.spec.ts @@ -57,7 +57,7 @@ describe('entityConfig', () => { selectId: selectId2, }); - const selectId3: SelectEntityId = (user) => user.key; + const selectId3: SelectEntityId = (user) => user.key; const userConfig3 = entityConfig({ entity: type(), selectId: selectId3, @@ -67,15 +67,15 @@ describe('entityConfig', () => { expectSnippet(snippet).toSucceed(); expectSnippet(snippet).toInfer( 'userConfig1', - '{ entity: User; selectId: SelectEntityId>; }' + '{ entity: User; selectId: SelectEntityId, number>; }' ); expectSnippet(snippet).toInfer( 'userConfig2', - '{ entity: User; selectId: SelectEntityId>; }' + '{ entity: User; selectId: SelectEntityId, number>; }' ); expectSnippet(snippet).toInfer( 'userConfig3', - '{ entity: User; selectId: SelectEntityId>; }' + '{ entity: User; selectId: SelectEntityId, number>; }' ); }); @@ -97,7 +97,7 @@ describe('entityConfig', () => { `).toFail(/No overload matches this call/); expectSnippet(` - const selectId: SelectEntityId<{ key: string }> = (entity) => entity.key; + const selectId: SelectEntityId<{ key: string }, string> = (entity) => entity.key; const userConfig = entityConfig({ entity: type(), @@ -121,7 +121,7 @@ describe('entityConfig', () => { selectId: selectId2, }); - const selectId3: SelectEntityId = (user) => user.key; + const selectId3: SelectEntityId = (user) => user.key; const userConfig3 = entityConfig({ entity: type(), collection: 'user', @@ -132,15 +132,15 @@ describe('entityConfig', () => { expectSnippet(snippet).toSucceed(); expectSnippet(snippet).toInfer( 'userConfig1', - '{ entity: User; collection: "user"; selectId: SelectEntityId>; }' + '{ entity: User; collection: "user"; selectId: SelectEntityId, number>; }' ); expectSnippet(snippet).toInfer( 'userConfig2', - '{ entity: User; collection: "user"; selectId: SelectEntityId>; }' + '{ entity: User; collection: "user"; selectId: SelectEntityId, number>; }' ); expectSnippet(snippet).toInfer( 'userConfig3', - '{ entity: User; collection: "user"; selectId: SelectEntityId>; }' + '{ entity: User; collection: "user"; selectId: SelectEntityId, number>; }' ); }); @@ -164,7 +164,7 @@ describe('entityConfig', () => { `).toFail(/No overload matches this call/); expectSnippet(` - const selectId: SelectEntityId<{ key: string }> = (entity) => entity.key; + const selectId: SelectEntityId<{ key: string }, string> = (entity) => entity.key; const userConfig = entityConfig({ entity: type(), diff --git a/modules/signals/entities/src/entity-config.ts b/modules/signals/entities/src/entity-config.ts index 8981fa7d5b..5e980e73c1 100644 --- a/modules/signals/entities/src/entity-config.ts +++ b/modules/signals/entities/src/entity-config.ts @@ -1,23 +1,27 @@ -import { SelectEntityId } from './models'; +import { EntityId, SelectEntityId } from './models'; -export function entityConfig(config: { +export function entityConfig< + Entity, + Collection extends string, + Id extends EntityId +>(config: { entity: Entity; collection: Collection; - selectId: SelectEntityId>; + selectId: SelectEntityId, Id>; }): typeof config; -export function entityConfig(config: { +export function entityConfig(config: { entity: Entity; - selectId: SelectEntityId>; + selectId: SelectEntityId, Id>; }): typeof config; export function entityConfig(config: { entity: Entity; collection: Collection; }): typeof config; export function entityConfig(config: { entity: Entity }): typeof config; -export function entityConfig(config: { +export function entityConfig(config: { entity: Entity; collection?: string; - selectId?: SelectEntityId; + selectId?: SelectEntityId; }): typeof config { return config; } diff --git a/modules/signals/entities/src/helpers.ts b/modules/signals/entities/src/helpers.ts index 0ed58ccb4a..09883a14ec 100644 --- a/modules/signals/entities/src/helpers.ts +++ b/modules/signals/entities/src/helpers.ts @@ -8,11 +8,12 @@ import { } from './models'; declare const ngDevMode: unknown; -const defaultSelectId: SelectEntityId<{ id: EntityId }> = (entity) => entity.id; +const defaultSelectId: SelectEntityId<{ id: EntityId }, EntityId> = (entity) => + entity.id; export function getEntityIdSelector(config?: { - selectId?: SelectEntityId; -}): SelectEntityId { + selectId?: SelectEntityId; +}): SelectEntityId { return config?.selectId ?? defaultSelectId; } @@ -37,7 +38,7 @@ export function cloneEntityState( entityMapKey: string; idsKey: string; } -): EntityState { +): EntityState { return { entityMap: { ...state[stateKeys.entityMapKey] }, ids: [...state[stateKeys.idsKey]], @@ -45,7 +46,7 @@ export function cloneEntityState( } export function getEntityUpdaterResult( - state: EntityState, + state: EntityState, stateKeys: { entityMapKey: string; idsKey: string; @@ -69,9 +70,9 @@ export function getEntityUpdaterResult( } export function addEntityMutably( - state: EntityState, + state: EntityState, entity: any, - selectId: SelectEntityId + selectId: SelectEntityId ): DidMutate { const id = selectId(entity); @@ -86,9 +87,9 @@ export function addEntityMutably( } export function addEntitiesMutably( - state: EntityState, + state: EntityState, entities: any[], - selectId: SelectEntityId + selectId: SelectEntityId ): DidMutate { let didMutate = DidMutate.None; @@ -104,9 +105,9 @@ export function addEntitiesMutably( } export function setEntityMutably( - state: EntityState, + state: EntityState, entity: any, - selectId: SelectEntityId + selectId: SelectEntityId ): DidMutate { const id = selectId(entity); @@ -122,9 +123,9 @@ export function setEntityMutably( } export function setEntitiesMutably( - state: EntityState, + state: EntityState, entities: any[], - selectId: SelectEntityId + selectId: SelectEntityId ): DidMutate { let didMutate = DidMutate.None; @@ -142,7 +143,7 @@ export function setEntitiesMutably( } export function removeEntitiesMutably( - state: EntityState, + state: EntityState, idsOrPredicate: EntityId[] | EntityPredicate ): DidMutate { const ids = Array.isArray(idsOrPredicate) @@ -165,10 +166,10 @@ export function removeEntitiesMutably( } export function updateEntitiesMutably( - state: EntityState, + state: EntityState, idsOrPredicate: EntityId[] | EntityPredicate, changes: EntityChanges, - selectId: SelectEntityId + selectId: SelectEntityId ): DidMutate { const ids = Array.isArray(idsOrPredicate) ? idsOrPredicate diff --git a/modules/signals/entities/src/models.ts b/modules/signals/entities/src/models.ts index 956311b50b..0e9d66f392 100644 --- a/modules/signals/entities/src/models.ts +++ b/modules/signals/entities/src/models.ts @@ -2,15 +2,22 @@ import { Signal } from '@angular/core'; export type EntityId = string | number; -export type EntityMap = Record; +export type EntityMap = Record; -export type EntityState = { - entityMap: EntityMap; - ids: EntityId[]; +export type EntityState = { + entityMap: EntityMap; + ids: Id[]; }; -export type NamedEntityState = { - [K in keyof EntityState as `${Collection}${Capitalize}`]: EntityState[K]; +export type NamedEntityState< + Entity, + Collection extends string, + Id extends EntityId +> = { + [K in keyof EntityState< + Entity, + Id + > as `${Collection}${Capitalize}`]: EntityState[K]; }; export type EntityProps = { @@ -21,7 +28,9 @@ export type NamedEntityProps = { [K in keyof EntityProps as `${Collection}${Capitalize}`]: EntityProps[K]; }; -export type SelectEntityId = (entity: Entity) => EntityId; +export type SelectEntityId = ( + entity: Entity +) => Id; export type EntityPredicate = (entity: Entity) => boolean; diff --git a/modules/signals/entities/src/updaters/add-entities.ts b/modules/signals/entities/src/updaters/add-entities.ts index dc26260ee7..5aeed272f0 100644 --- a/modules/signals/entities/src/updaters/add-entities.ts +++ b/modules/signals/entities/src/updaters/add-entities.ts @@ -13,28 +13,39 @@ import { getEntityUpdaterResult, } from '../helpers'; -export function addEntities( - entities: Entity[] -): PartialStateUpdater>; -export function addEntities( +export function addEntities< + Entity extends { id: EntityId }, + Id extends EntityId = Entity extends { id: infer E } ? E : never +>(entities: Entity[]): PartialStateUpdater>; +export function addEntities< + Entity, + Collection extends string, + Id extends EntityId +>( entities: Entity[], - config: { collection: Collection; selectId: SelectEntityId> } -): PartialStateUpdater>; + config: { + collection: Collection; + selectId: SelectEntityId, Id>; + } +): PartialStateUpdater>; export function addEntities< Entity extends { id: EntityId }, - Collection extends string + Collection extends string, + Id extends EntityId = Entity extends { id: infer E } ? E : never >( entities: Entity[], config: { collection: Collection } -): PartialStateUpdater>; -export function addEntities( +): PartialStateUpdater>; +export function addEntities( entities: Entity[], - config: { selectId: SelectEntityId> } -): PartialStateUpdater>; + config: { selectId: SelectEntityId, Id> } +): PartialStateUpdater>; export function addEntities( entities: any[], - config?: { collection?: string; selectId?: SelectEntityId } -): PartialStateUpdater | NamedEntityState> { + config?: { collection?: string; selectId?: SelectEntityId } +): PartialStateUpdater< + EntityState | NamedEntityState +> { const selectId = getEntityIdSelector(config); const stateKeys = getEntityStateKeys(config); diff --git a/modules/signals/entities/src/updaters/add-entity.ts b/modules/signals/entities/src/updaters/add-entity.ts index cdd4ee4b5a..749fc2430e 100644 --- a/modules/signals/entities/src/updaters/add-entity.ts +++ b/modules/signals/entities/src/updaters/add-entity.ts @@ -13,28 +13,39 @@ import { getEntityUpdaterResult, } from '../helpers'; -export function addEntity( - entity: Entity -): PartialStateUpdater>; -export function addEntity( +export function addEntity< + Entity extends { id: EntityId }, + Id extends EntityId = Entity extends { id: infer E } ? E : never +>(entity: Entity): PartialStateUpdater>; +export function addEntity< + Entity, + Collection extends string, + Id extends EntityId +>( entity: Entity, - config: { collection: Collection; selectId: SelectEntityId> } -): PartialStateUpdater>; + config: { + collection: Collection; + selectId: SelectEntityId, Id>; + } +): PartialStateUpdater>; export function addEntity< Entity extends { id: EntityId }, - Collection extends string + Collection extends string, + Id extends EntityId = Entity extends { id: infer E } ? E : never >( entity: Entity, config: { collection: Collection } -): PartialStateUpdater>; -export function addEntity( +): PartialStateUpdater>; +export function addEntity( entity: Entity, - config: { selectId: SelectEntityId> } -): PartialStateUpdater>; + config: { selectId: SelectEntityId, Id> } +): PartialStateUpdater>; export function addEntity( entity: any, - config?: { collection?: string; selectId?: SelectEntityId } -): PartialStateUpdater | NamedEntityState> { + config?: { collection?: string; selectId?: SelectEntityId } +): PartialStateUpdater< + EntityState | NamedEntityState +> { const selectId = getEntityIdSelector(config); const stateKeys = getEntityStateKeys(config); diff --git a/modules/signals/entities/src/updaters/remove-all-entities.ts b/modules/signals/entities/src/updaters/remove-all-entities.ts index df35cc2e58..f3d9787557 100644 --- a/modules/signals/entities/src/updaters/remove-all-entities.ts +++ b/modules/signals/entities/src/updaters/remove-all-entities.ts @@ -1,14 +1,16 @@ import { PartialStateUpdater } from '@ngrx/signals'; -import { EntityState, NamedEntityState } from '../models'; +import { EntityId, EntityState, NamedEntityState } from '../models'; import { getEntityStateKeys } from '../helpers'; -export function removeAllEntities(): PartialStateUpdater>; +export function removeAllEntities(): PartialStateUpdater>; export function removeAllEntities(config: { collection: Collection; -}): PartialStateUpdater>; +}): PartialStateUpdater>; export function removeAllEntities(config?: { collection?: string; -}): PartialStateUpdater | NamedEntityState> { +}): PartialStateUpdater< + EntityState | NamedEntityState +> { const stateKeys = getEntityStateKeys(config); return () => ({ diff --git a/modules/signals/entities/src/updaters/remove-entities.ts b/modules/signals/entities/src/updaters/remove-entities.ts index 54696c3706..71de07e73b 100644 --- a/modules/signals/entities/src/updaters/remove-entities.ts +++ b/modules/signals/entities/src/updaters/remove-entities.ts @@ -12,20 +12,20 @@ import { removeEntitiesMutably, } from '../helpers'; -export function removeEntities( - ids: EntityId[] -): PartialStateUpdater>; +export function removeEntities( + ids: Id[] +): PartialStateUpdater>; export function removeEntities( predicate: EntityPredicate -): PartialStateUpdater>; -export function removeEntities( - ids: EntityId[], +): PartialStateUpdater>; +export function removeEntities( + ids: Id[], config: { collection: Collection } -): PartialStateUpdater>; +): PartialStateUpdater>; export function removeEntities< Collection extends string, - State extends NamedEntityState, - Entity = State extends NamedEntityState ? E : never + State extends NamedEntityState, + Entity = State extends NamedEntityState ? E : never >( predicate: EntityPredicate, config: { collection: Collection } @@ -33,7 +33,9 @@ export function removeEntities< export function removeEntities( idsOrPredicate: EntityId[] | EntityPredicate, config?: { collection?: string } -): PartialStateUpdater | NamedEntityState> { +): PartialStateUpdater< + EntityState | NamedEntityState +> { const stateKeys = getEntityStateKeys(config); return (state) => { diff --git a/modules/signals/entities/src/updaters/remove-entity.ts b/modules/signals/entities/src/updaters/remove-entity.ts index d0057a60c2..0e3993f6f8 100644 --- a/modules/signals/entities/src/updaters/remove-entity.ts +++ b/modules/signals/entities/src/updaters/remove-entity.ts @@ -7,17 +7,19 @@ import { removeEntitiesMutably, } from '../helpers'; -export function removeEntity( - id: EntityId -): PartialStateUpdater>; -export function removeEntity( - id: EntityId, +export function removeEntity( + id: Id +): PartialStateUpdater>; +export function removeEntity( + id: Id, config: { collection: Collection } -): PartialStateUpdater>; +): PartialStateUpdater>; export function removeEntity( id: EntityId, config?: { collection?: string } -): PartialStateUpdater | NamedEntityState> { +): PartialStateUpdater< + EntityState | NamedEntityState +> { const stateKeys = getEntityStateKeys(config); return (state) => { diff --git a/modules/signals/entities/src/updaters/set-all-entities.ts b/modules/signals/entities/src/updaters/set-all-entities.ts index 3a2c56b799..73335168b8 100644 --- a/modules/signals/entities/src/updaters/set-all-entities.ts +++ b/modules/signals/entities/src/updaters/set-all-entities.ts @@ -11,33 +11,44 @@ import { setEntitiesMutably, } from '../helpers'; -export function setAllEntities( - entities: Entity[] -): PartialStateUpdater>; -export function setAllEntities( +export function setAllEntities< + Entity extends { id: EntityId }, + Id extends EntityId = Entity extends { id: infer E } ? E : never +>(entities: Entity[]): PartialStateUpdater>; +export function setAllEntities< + Entity, + Collection extends string, + Id extends EntityId +>( entities: Entity[], - config: { collection: Collection; selectId: SelectEntityId> } -): PartialStateUpdater>; + config: { + collection: Collection; + selectId: SelectEntityId, Id>; + } +): PartialStateUpdater>; export function setAllEntities< Entity extends { id: EntityId }, - Collection extends string + Collection extends string, + Id extends EntityId = Entity extends { id: infer E } ? E : never >( entities: Entity[], config: { collection: Collection } -): PartialStateUpdater>; -export function setAllEntities( +): PartialStateUpdater>; +export function setAllEntities( entities: Entity[], - config: { selectId: SelectEntityId> } -): PartialStateUpdater>; + config: { selectId: SelectEntityId, Id> } +): PartialStateUpdater>; export function setAllEntities( entities: any[], - config?: { collection?: string; selectId?: SelectEntityId } -): PartialStateUpdater | NamedEntityState> { + config?: { collection?: string; selectId?: SelectEntityId } +): PartialStateUpdater< + EntityState | NamedEntityState +> { const selectId = getEntityIdSelector(config); const stateKeys = getEntityStateKeys(config); return () => { - const state: EntityState = { entityMap: {}, ids: [] }; + const state: EntityState = { entityMap: {}, ids: [] }; setEntitiesMutably(state, entities, selectId); return { diff --git a/modules/signals/entities/src/updaters/set-entities.ts b/modules/signals/entities/src/updaters/set-entities.ts index c6339a0cb6..cf281e408a 100644 --- a/modules/signals/entities/src/updaters/set-entities.ts +++ b/modules/signals/entities/src/updaters/set-entities.ts @@ -13,28 +13,39 @@ import { setEntitiesMutably, } from '../helpers'; -export function setEntities( - entities: Entity[] -): PartialStateUpdater>; -export function setEntities( +export function setEntities< + Entity extends { id: EntityId }, + Id extends EntityId = Entity extends { id: infer E } ? E : never +>(entities: Entity[]): PartialStateUpdater>; +export function setEntities< + Entity, + Collection extends string, + Id extends EntityId +>( entities: Entity[], - config: { collection: Collection; selectId: SelectEntityId> } -): PartialStateUpdater>; + config: { + collection: Collection; + selectId: SelectEntityId, Id>; + } +): PartialStateUpdater>; export function setEntities< Entity extends { id: EntityId }, - Collection extends string + Collection extends string, + Id extends EntityId = Entity extends { id: infer E } ? E : never >( entities: Entity[], config: { collection: Collection } -): PartialStateUpdater>; -export function setEntities( +): PartialStateUpdater>; +export function setEntities( entities: Entity[], - config: { selectId: SelectEntityId> } -): PartialStateUpdater>; + config: { selectId: SelectEntityId, Id> } +): PartialStateUpdater>; export function setEntities( entities: any[], - config?: { collection?: string; selectId?: SelectEntityId } -): PartialStateUpdater | NamedEntityState> { + config?: { collection?: string; selectId?: SelectEntityId } +): PartialStateUpdater< + EntityState | NamedEntityState +> { const selectId = getEntityIdSelector(config); const stateKeys = getEntityStateKeys(config); diff --git a/modules/signals/entities/src/updaters/set-entity.ts b/modules/signals/entities/src/updaters/set-entity.ts index d9dd1f1b98..4540408a51 100644 --- a/modules/signals/entities/src/updaters/set-entity.ts +++ b/modules/signals/entities/src/updaters/set-entity.ts @@ -13,28 +13,39 @@ import { setEntityMutably, } from '../helpers'; -export function setEntity( - entity: Entity -): PartialStateUpdater>; -export function setEntity( +export function setEntity< + Entity extends { id: EntityId }, + Id extends EntityId = Entity extends { id: infer E } ? E : never +>(entity: Entity): PartialStateUpdater>; +export function setEntity< + Entity, + Collection extends string, + Id extends EntityId +>( entity: Entity, - config: { collection: Collection; selectId: SelectEntityId> } -): PartialStateUpdater>; + config: { + collection: Collection; + selectId: SelectEntityId, Id>; + } +): PartialStateUpdater>; export function setEntity< Entity extends { id: EntityId }, - Collection extends string + Collection extends string, + Id extends EntityId = Entity extends { id: infer E } ? E : never >( entity: Entity, config: { collection: Collection } -): PartialStateUpdater>; -export function setEntity( +): PartialStateUpdater>; +export function setEntity( entity: Entity, - config: { selectId: SelectEntityId> } -): PartialStateUpdater>; + config: { selectId: SelectEntityId, Id> } +): PartialStateUpdater>; export function setEntity( entity: any, - config?: { collection?: string; selectId?: SelectEntityId } -): PartialStateUpdater | NamedEntityState> { + config?: { collection?: string; selectId?: SelectEntityId } +): PartialStateUpdater< + EntityState | NamedEntityState +> { const selectId = getEntityIdSelector(config); const stateKeys = getEntityStateKeys(config); diff --git a/modules/signals/entities/src/updaters/update-all-entities.ts b/modules/signals/entities/src/updaters/update-all-entities.ts index 9618997b96..2d4b9d1ef0 100644 --- a/modules/signals/entities/src/updaters/update-all-entities.ts +++ b/modules/signals/entities/src/updaters/update-all-entities.ts @@ -16,39 +16,55 @@ import { export function updateAllEntities< Collection extends string, - State extends NamedEntityState, - Entity = State extends NamedEntityState ? E : never + State extends NamedEntityState, + Id extends EntityId, + Entity = State extends NamedEntityState ? E : never >( changes: EntityChanges>, config: { collection: Collection; - selectId: SelectEntityId>; + selectId: SelectEntityId, Id>; } ): PartialStateUpdater; export function updateAllEntities< Collection extends string, - State extends NamedEntityState, + State extends NamedEntityState, Entity = State extends NamedEntityState< infer E extends { id: EntityId }, - Collection + Collection, + EntityId > ? E + : never, + Id extends EntityId = State extends NamedEntityState< + infer E extends { id: EntityId }, + Collection, + EntityId + > + ? E extends { id: infer T } + ? T + : never : never >( changes: EntityChanges>, config: { collection: Collection } ): PartialStateUpdater; -export function updateAllEntities( +export function updateAllEntities( changes: EntityChanges>, - config: { selectId: SelectEntityId> } -): PartialStateUpdater>; -export function updateAllEntities( + config: { selectId: SelectEntityId, Id> } +): PartialStateUpdater>; +export function updateAllEntities< + Entity extends { id: EntityId }, + Id extends EntityId = Entity extends { id: infer E } ? E : never +>( changes: EntityChanges> -): PartialStateUpdater>; +): PartialStateUpdater>; export function updateAllEntities( changes: EntityChanges, - config?: { collection?: string; selectId?: SelectEntityId } -): PartialStateUpdater | NamedEntityState> { + config?: { collection?: string; selectId?: SelectEntityId } +): PartialStateUpdater< + EntityState | NamedEntityState +> { const selectId = getEntityIdSelector(config); const stateKeys = getEntityStateKeys(config); diff --git a/modules/signals/entities/src/updaters/update-entities.ts b/modules/signals/entities/src/updaters/update-entities.ts index f6cc101634..5386a769c6 100644 --- a/modules/signals/entities/src/updaters/update-entities.ts +++ b/modules/signals/entities/src/updaters/update-entities.ts @@ -17,22 +17,34 @@ import { export function updateEntities< Collection extends string, - State extends NamedEntityState, - Entity = State extends NamedEntityState ? E : never + State extends NamedEntityState, + Id extends EntityId, + Entity = State extends NamedEntityState ? E : never >( update: { - ids: EntityId[]; + ids: Id[]; changes: EntityChanges>; }, config: { collection: Collection; - selectId: SelectEntityId>; + selectId: SelectEntityId, Id>; } ): PartialStateUpdater; export function updateEntities< Collection extends string, - State extends NamedEntityState, - Entity = State extends NamedEntityState ? E : never + State extends NamedEntityState, + Entity = State extends NamedEntityState + ? E + : never, + Id extends EntityId = State extends NamedEntityState< + infer E, + Collection, + EntityId + > + ? E extends { id: infer T } + ? T + : never + : never >( update: { predicate: EntityPredicate; @@ -40,33 +52,53 @@ export function updateEntities< }, config: { collection: Collection; - selectId: SelectEntityId>; + selectId: SelectEntityId, Id>; } ): PartialStateUpdater; export function updateEntities< Collection extends string, - State extends NamedEntityState, + State extends NamedEntityState, Entity = State extends NamedEntityState< infer E extends { id: EntityId }, - Collection + Collection, + EntityId > ? E + : never, + Id extends EntityId = State extends NamedEntityState< + infer E extends { id: EntityId }, + Collection, + EntityId + > + ? E extends { id: infer T } + ? T + : never : never >( update: { - ids: EntityId[]; + ids: Id[]; changes: EntityChanges>; }, config: { collection: Collection } ): PartialStateUpdater; export function updateEntities< Collection extends string, - State extends NamedEntityState, + State extends NamedEntityState, Entity = State extends NamedEntityState< infer E extends { id: EntityId }, - Collection + Collection, + EntityId > ? E + : never, + Id extends EntityId = State extends NamedEntityState< + infer E extends { id: EntityId }, + Collection, + EntityId + > + ? E extends { id: infer T } + ? T + : never : never >( update: { @@ -75,34 +107,42 @@ export function updateEntities< }, config: { collection: Collection } ): PartialStateUpdater; -export function updateEntities( +export function updateEntities( update: { - ids: EntityId[]; + ids: Id[]; changes: EntityChanges>; }, - config: { selectId: SelectEntityId> } -): PartialStateUpdater>; -export function updateEntities( + config: { selectId: SelectEntityId, Id> } +): PartialStateUpdater>; +export function updateEntities( update: { predicate: EntityPredicate; changes: EntityChanges>; }, - config: { selectId: SelectEntityId> } -): PartialStateUpdater>; -export function updateEntities(update: { - ids: EntityId[]; + config: { selectId: SelectEntityId, Id> } +): PartialStateUpdater>; +export function updateEntities< + Entity extends { id: EntityId }, + Id extends EntityId = Entity extends { id: infer E } ? E : never +>(update: { + ids: Id[]; changes: EntityChanges>; -}): PartialStateUpdater>; -export function updateEntities(update: { +}): PartialStateUpdater>; +export function updateEntities< + Entity extends { id: EntityId }, + Id extends EntityId = Entity extends { id: infer E } ? E : never +>(update: { predicate: EntityPredicate; changes: EntityChanges>; -}): PartialStateUpdater>; +}): PartialStateUpdater>; export function updateEntities( update: ({ ids: EntityId[] } | { predicate: EntityPredicate }) & { changes: EntityChanges; }, - config?: { collection?: string; selectId?: SelectEntityId } -): PartialStateUpdater | NamedEntityState> { + config?: { collection?: string; selectId?: SelectEntityId } +): PartialStateUpdater< + EntityState | NamedEntityState +> { const selectId = getEntityIdSelector(config); const stateKeys = getEntityStateKeys(config); const idsOrPredicate = 'ids' in update ? update.ids : update.predicate; diff --git a/modules/signals/entities/src/updaters/update-entity.ts b/modules/signals/entities/src/updaters/update-entity.ts index 72585f6c50..138c7fe03c 100644 --- a/modules/signals/entities/src/updaters/update-entity.ts +++ b/modules/signals/entities/src/updaters/update-entity.ts @@ -16,52 +16,68 @@ import { export function updateEntity< Collection extends string, - State extends NamedEntityState, - Entity = State extends NamedEntityState ? E : never + State extends NamedEntityState, + Id extends EntityId, + Entity = State extends NamedEntityState ? E : never >( update: { - id: EntityId; + id: Id; changes: EntityChanges>; }, config: { collection: Collection; - selectId: SelectEntityId>; + selectId: SelectEntityId, Id>; } ): PartialStateUpdater; export function updateEntity< Collection extends string, - State extends NamedEntityState, + State extends NamedEntityState, Entity = State extends NamedEntityState< infer E extends { id: EntityId }, - Collection + Collection, + EntityId > ? E + : never, + Id extends EntityId = State extends NamedEntityState< + infer E extends { id: EntityId }, + Collection, + EntityId + > + ? E extends { id: infer T } + ? T + : never : never >( update: { - id: EntityId; + id: Id; changes: EntityChanges>; }, config: { collection: Collection } ): PartialStateUpdater; -export function updateEntity( +export function updateEntity( update: { - id: EntityId; + id: Id; changes: EntityChanges>; }, - config: { selectId: SelectEntityId> } -): PartialStateUpdater>; -export function updateEntity(update: { - id: EntityId; + config: { selectId: SelectEntityId, Id> } +): PartialStateUpdater>; +export function updateEntity< + Entity extends { id: EntityId }, + Id extends EntityId = Entity extends { id: infer E } ? E : never +>(update: { + id: Id; changes: EntityChanges>; -}): PartialStateUpdater>; +}): PartialStateUpdater>; export function updateEntity( update: { id: EntityId; changes: EntityChanges; }, - config?: { collection?: string; selectId?: SelectEntityId } -): PartialStateUpdater | NamedEntityState> { + config?: { collection?: string; selectId?: SelectEntityId } +): PartialStateUpdater< + EntityState | NamedEntityState +> { const selectId = getEntityIdSelector(config); const stateKeys = getEntityStateKeys(config); diff --git a/modules/signals/entities/src/with-entities.ts b/modules/signals/entities/src/with-entities.ts index 2177c6afe1..84de9a6e40 100644 --- a/modules/signals/entities/src/with-entities.ts +++ b/modules/signals/entities/src/with-entities.ts @@ -13,34 +13,72 @@ import { EntityState, NamedEntityProps, NamedEntityState, + SelectEntityId, } from './models'; import { getEntityStateKeys } from './helpers'; -export function withEntities(): SignalStoreFeature< +export function withEntities< + Entity extends { id: EntityId }, + Id extends EntityId = Entity extends { id: infer E } ? E : never +>(): SignalStoreFeature< EmptyFeatureResult, { - state: EntityState; + state: EntityState; props: EntityProps; methods: {}; } >; -export function withEntities(config: { +export function withEntities< + Entity, + Collection extends string, + Id extends EntityId +>(config: { entity: Entity; collection: Collection; + selectId: SelectEntityId, Id>; }): SignalStoreFeature< EmptyFeatureResult, { - state: NamedEntityState; + state: NamedEntityState; props: NamedEntityProps; methods: {}; } >; -export function withEntities(config: { +export function withEntities< + Entity extends { id: EntityId }, + Collection extends string, + Id extends EntityId = Entity extends { id: infer E } ? E : never +>(config: { + entity: Entity; + collection: Collection; +}): SignalStoreFeature< + EmptyFeatureResult, + { + state: NamedEntityState; + props: NamedEntityProps; + methods: {}; + } +>; +export function withEntities(config: { + entity: Entity; + selectId: SelectEntityId, Id>; +}): SignalStoreFeature< + EmptyFeatureResult, + { + state: EntityState; + props: EntityProps; + methods: {}; + } +>; +export function withEntities< + Entity extends { id: EntityId }, + Id extends EntityId = Entity extends { id: infer E } ? E : never +>(config: { entity: Entity; }): SignalStoreFeature< EmptyFeatureResult, { - state: EntityState; + state: EntityState; props: EntityProps; methods: {}; } @@ -58,7 +96,7 @@ export function withEntities(config?: { }), withComputed((store: Record>) => ({ [entitiesKey]: computed(() => { - const entityMap = store[entityMapKey]() as EntityMap; + const entityMap = store[entityMapKey]() as EntityMap; const ids = store[idsKey]() as EntityId[]; return ids.map((id) => entityMap[id]);