withCngxAsyncState
projects/interop/signals/with-cngx-async-state.ts
Description#
@ngrx/signals store feature that grants a store a CngxAsyncState-shaped
slice with zero hand-written status flags.
The element type is supplied up front and the key is inferred from the
argument, so the two contributed members carry the literal key:
withCngxAsyncState<User[]>()('users') adds usersState (the read-only
CngxAsyncState<User[]> view) and usersSink (the writable
ManualAsyncState<User[]>). Drive the status with the existing
tapAsyncState operator - no new state machine, no manual isLoading
boolean. Both members are the same underlying createManualState instance,
exposed under a read type and a write type.
The <T>() / (key) split is deliberate: TypeScript cannot infer the
literal key while T is given explicitly in one call, so a single-call
form collapses the key to a string index signature. Currying keeps the
key literal - and therefore the store members concretely named.
export const UsersStore = signalStore(
withCngxAsyncState<User[]>()('users'),
withMethods((store) => {
const http = inject(HttpClient);
return {
load: () =>
http.get<User[]>('/api/users').pipe(
tapAsyncState(store.usersSink),
takeUntilDestroyed(),
).subscribe(),
};
}),
);
// store.usersState.status(), store.usersState.data() - derived, no flags