The project I'm currently working on uses NGXS. In one component there is a FormControl-factory that is used to create typed form-control instances that dispatch actions of the given type whenever the form-control's value changes:
private createControl<T, U>(actionConstructor: new (val: T) => U, initialValue: T): FormControl<T> {
const ctrl = new FormControl<T>(initialValue);
this.subscriptions.push( // subscriptions is field in the component
ctrl.valueChanges.subscribe({
next: val => {
this.store.dispatch(new actionConstructor(val)); // store is field in the component
}
})
);
return ctrl;
}
The factory is then called like this:
this.setNameCtrl = this.createControl(SetName, 'Bob');
SetName is an (ngxs) action:
export class SetName {
static readonly type = '[App] Set Name';
constructor(public name: string) {}
}
I'm now attempting to update NGXS from 18.1.3 to 18.1.4, which among other things now disallows nullable actions being passed to dispatch(). TypeScript now tells
TS2345: Argument of type 'U' is not assignable to parameter of type 'ActionOrArrayOfActions'
and I can't for the life of me work out what I have to change to make the compiler happy. The type ActionOrArrayOfActions is part of NGXS and defined as follows:
type ActionOrArrayOfActions<T> = T extends (infer U)[] ? NonNullable<U>[] : NonNullable<T>;
Does the generic type U have to be constrained in a certain way? Any help would be much appreciated.
We kinda had the same issue.
We ended up copying the ActionOrArrayOfActions definition into our own codebase, since its not (yet?) exposed from ngxs and then just defining our U to be of that type.
In your case it would probably look something like this:
private createControl<T, U>(actionConstructor: new (val: T) => ActionOrArrayOfActions<U>, initialValue: T): FormControl<T> {
const ctrl = new FormControl<T>(initialValue);
this.subscriptions.push( // subscriptions is field in the component
ctrl.valueChanges.subscribe({
next: val => {
this.store.dispatch(new actionConstructor(val)); // store is field in the component
}
})
);
return ctrl;
}
with having
export type ActionOrArrayOfActions<T> = T extends (infer U)[] ? NonNullable<U>[] : NonNullable<T>;
defined somewhere.
Maybe it helps :)