-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[signals] Potential typing bug when using discriminated unions #4467
Comments
The error goes away if you just have const _Store = signalStore(
{ providedIn: 'root' },
withState(initialState)
);
|
Thanks @rainerhahnekamp! That works for now (as a workaround) 👍🏽 |
@markostanimirovic, if that's the right approach for now, should we leave a note in the docs? |
@rainerhahnekamp — I spoke too soon — unfortunately it still fails elsewhere, when using the discriminated union types. I've updated the Stackblitz to show this (https://stackblitz.com/edit/stackblitz-starters-ucjue4?file=src%2Fstore.ts). Looks like the inferred state type of the store is not picking up the full discriminated union, just the specific type of |
Union types can be used for state properties, not for the entire state because SignalStore/SignalState generates state signals based on the initial state. // From:
type State = A | B;
const initialState: State = { /* ... */ };
// To:
type State = { prop: A | B };
const initialState: State = { prop: /* ... */ }; We can add a section about unions to the FAQ page and update the answer for the "Can I define my SignalStore as a class?" question to contain a note that although it's possible to create a class-based SignalStore, using the functional style is recommended. |
@markostanimirovic — ahh, that's a shame! I've been using discriminated union types (with extended class) up until (and including) RC2. Is there anything that can be done to support this use case, as I feel it's more akin to modelling state like a state machine, and gives us much better type safety. I'm keen to use this with extended classes so I can add extra properties etc. (as mentioned in #4141 (reply in thread)). A concrete example of where I'm doing this (an |
@jits. nested state with union works. We can take that as workaround type A = {
status: 'A';
thing: null;
};
type B = {
status: 'B';
thing: string;
};
type NestedState = A | B;
type State = { nested: NestedState };
const initialState: State = { nested: { status: 'A', thing: null } };
const _Store = signalStore(
{ providedIn: 'root' },
withState(initialState),
withMethods((store) => {
return {
updateToB(thing: string): void {
const newState: B = { status: 'B', thing };
patchState(store, { nested: newState });
},
};
})
); |
Thank you for the detailed explanation @jits! We'll consider adding a In the meantime, I suggest a different approach. Instead of extending a SignalStore, you can create a class that injects it: const AuthStore = signalStore({ providedIn: 'root' }, /* ... */);
@Injectable({ providedIn: 'root' })
export class AuthFacade {
readonly #store = inject(AuthStore);
// ... expose all public store APIs
// ... add additional properties
} By the way, discriminated unions for the entire state work with functional SignalStores: https://stackblitz.com/edit/stackblitz-starters-hefo5v?file=src%2Fstore.ts |
Thanks for clarifying @markostanimirovic, and for your suggestions. Sounds like functional SignalStores are the way forward. A future Congrats to you and the team on the NgRx SignalStore first stable release! 🎉 (Please feel free to close this issue if no further action is needed.) |
Which @ngrx/* package(s) are the source of the bug?
signals
Minimal reproduction of the bug/regression with instructions
See https://stackblitz.com/edit/stackblitz-starters-ucjue4?file=src%2Fstore.ts
For posterity, here is the code that causes the typing error:
The typing error occurs on the line
export class Store extends _Store {}
, with the following TypeScript error:Expected behavior
Should compile fine and not give any TypeScript errors.
Versions of NgRx, Angular, Node, affected browser(s) and operating system(s)
NgRx: v18.0.0
Angular: latest v18
TypeScript: v5.5
Other information
No response
I would be willing to submit a PR to fix this issue
The text was updated successfully, but these errors were encountered: