Help with Typings needed #4506
-
I want to create features for my stores. I started with a simple one, which didn't need typing. I have no idea, how to type the store for the factory correctly, since all interfaces which are used in withMethods are not exported. import { patchState, signalStoreFeature, StateSignal, type, withMethods } from '@ngrx/signals';
import { inject, Type } from '@angular/core';
import { Observable } from 'rxjs';
import { ErrorType, setError, setLoaded, setLoading } from '../call-state';
import { SignalStoreFeatureResult, SignalStoreSlices } from '@ngrx/signals/src/signal-store-models';
import { Prettify } from '@ngrx/signals/src/ts-helpers';
function _setItem<T>(store: StateSignal<any> & { clearStack?: () => void }, item: T | null, clear: boolean) {
patchState(store, { item, ...setLoaded() });
if (clear && store.clearStack)
store.clearStack();
}
function _setError<T>(store: StateSignal<any> & { clearStack?: () => void }, error: ErrorType) {
patchState(store, { item: null, ...setError(error) });
if (store.clearStack)
store.clearStack();
}
type CrdMethodsFactory<Input extends SignalStoreFeatureResult, T, C, S> = (store: Prettify<SignalStoreSlices<Input['state']> & Input['signals'] & Input['methods'] & StateSignal<Prettify<Input['state']>>>) => CrdMethods<T, C, S>;
type CrdMethods<T, C, S> = {
getter: (client: S, id: string) => Observable<T>,
creator: (client: S, item: C) => Observable<string>
}
export function withCrd<Input extends SignalStoreFeatureResult, T, C, S>(factory: CrdMethodsFactory<Input, T, C, S>, service: Type<S>) {
return signalStoreFeature(
{
state: {
id: type<string | null>(),
item: type<T | null>()
}
},
withMethods(store => {
// @ts-ignore
const result = factory(store);
const client = inject(service);
return {
setId(id: string | null) {
const changed = store.id() !== id;
patchState(store, { id, ...setLoading() });
if (id)
result.getter(client, id).subscribe({
next: item => _setItem(store, item, changed),
error: error => _setError(store, error)
});
else
_setItem(store, null, true);
},
create(item: C) {
return result.creator(client, item);
}
};
})
);
} export const ExampleStore = signalStore(
{ providedIn: 'root' },
withMethods(store => ({
_updateRelations(data: any) {
/* request other data */
return of(data)
}
})),
withCrd(store => ({
getter: (client, id) => client.get(id).pipe(
switchMap(data => store._updateRelations(data)) // <- compile error since _updateRelations is type of () => unknown
),
creator: (client, request: any) => client.create(request)
}), Client)
) |
Beta Was this translation helpful? Give feedback.
Replies: 5 comments 5 replies
-
Hey @markusahrweileramcon, could you maybe set that one up with the official StackBlitz version at https://stackblitz.com/github/ngrx/signal-store-starter?file=src%2Fmain.ts? |
Beta Was this translation helpful? Give feedback.
-
@rainerhahnekamp here you go |
Beta Was this translation helpful? Give feedback.
-
Here's my current status: https://stackblitz.com/edit/github-swmcpq-ctbfgr?file=src%2Fwith-crd.feature.ts It works without importing internal stuff but the type inference for the store in your factory doesn't work. Let me know if you managed to fix it. Would be curious. In the meantime, I try out a different approach. |
Beta Was this translation helpful? Give feedback.
-
And here's a prototype of a working, alternate version: https://stackblitz.com/edit/github-sf729z?file=src%2Fspecial-store.ts A little bit clumsy, but hopefully a good starting point. Let me know, if I should investigate more time in improving it. |
Beta Was this translation helpful? Give feedback.
-
Thanks for your reply. I realized, that i was still on the 18 beta version. https://stackblitz.com/edit/github-sf729z-dqd3ha?file=src%2Fspecial-store.ts |
Beta Was this translation helpful? Give feedback.
And here's a prototype of a working, alternate version: https://stackblitz.com/edit/github-sf729z?file=src%2Fspecial-store.ts
A little bit clumsy, but hopefully a good starting point. Let me know, if I should investigate more time in improving it.