-
-
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
signalState is not creating DeepSignal property signals when the value object is an instance of a class #4604
Labels
Comments
3 tasks
Hi @vtachkov, I haven’t found a solution yet. I’ve shared my PR with the experiments I’ve tried so far. If you or anyone else discovers a solution, your input would be greatly appreciated! |
Here is the link to the TypeScript Playground which shows the current status. it is not working btw. Any help is highly appreciated. For your convenience, here's the code: export type Prettify<T> = { [K in keyof T]: T[K] } & {};
export type IsRecord<T> = T extends object
? T extends unknown[]
? false
: T extends Set<unknown>
? false
: T extends Map<unknown, unknown>
? false
: T extends Function
? false
: T extends { prototype: unknown } // check for constructor did not work
? false
: T extends { [key: string]: unknown }
? true
: false
: false;
export type IsUnknownRecord<T> = string extends keyof T
? true
: number extends keyof T
? true
: false;
export type IsKnownRecord<T> = IsRecord<T> extends true
? IsUnknownRecord<T> extends true
? false
: true
: false;
export type OmitPrivate<T> = {
[K in keyof T as K extends `_${string}` ? never : K]: T[K];
};
type NgSignal<T> = {set(value: T): void, update: (updateFn: (value: T) => T) => void} & (() => T)
// An extended Signal type that enables the correct typing
// of nested signals with the `name` or `length` key.
export interface Signal<T> extends NgSignal<T> {
name: unknown;
length: unknown;
}
export type DeepSignal<T> = Signal<T> &
(IsKnownRecord<T> extends true
? Readonly<{
[K in keyof T]: IsKnownRecord<T[K]> extends true
? DeepSignal<T[K]>
: Signal<T[K]>;
}>
: unknown);
declare function signalState<T>(value: T): DeepSignal<T>;
class User {
id = 0;
name = 'Konrad';
}
const state = {
user: new User(),
id: 1,
address: { city: 'Wien', zip: '1040' },
};
type AssertFalse<T extends false> = T;
type AssertTrue<T extends true> = T;
type IsType<Actual, Expected> = Expected extends Actual ? Actual extends Expected ? true : false;
const store = signalState(state);
type T1 = AssertFalse<IsRecord<User>>;
type T2 = AssertFalse<IsRecord<typeof state.id>>;
type T3 = AssertTrue<IsRecord<typeof state.address>>;
type T4 = AssertTrue<IsType<typeof store.address, DeepSignal<{city: string, zip: string}>>;
type T5 = AssertTrue<IsType<typeof store.user, Signal<User>>;
type T6 = AssertFalse<IsType<typeof store.user, DeepSignal<User>>; // fails because it is also true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Which @ngrx/* package(s) are the source of the bug?
signals
Minimal reproduction of the bug/regression with instructions
Using signalState, create a new store where the type of the value in the store is a class, and the value is set to an instance of that class. The documentation states that when the value in the store is an object, signals will be created for each property on the object (DeepSignal). But in the case where the object is a class instance, signals are not being created for each property, they are undefined.
If this isn't supported, that's one thing, but TypeScript still types each property on the value as a signal.
Minimal reproduction: https://stackblitz.com/edit/typescript-dxfawb?file=index.ts
Expected behavior
Signals are created for each property on the signalStore value when the value is an instance of a class.
Versions of NgRx, Angular, Node, affected browser(s) and operating system(s)
NgRx: 18+
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: