addSelector

This commit is contained in:
Yanick Champoux 2024-08-12 11:34:24 -04:00
parent eec442ff68
commit 93582bcb70
2 changed files with 32 additions and 3 deletions

View File

@ -81,6 +81,9 @@ export default class Updux<D extends DuxConfig> {
/** @internal */
#inheritedReducer: (state: DuxState<D> | undefined, action: AnyAction) => DuxState<D>;
/** @internal */
#selectors = {};
constructor(private readonly duxConfig: D) {
if (duxConfig.subduxes)
this.#subduxes = D.map(duxConfig.subduxes, (s) =>
@ -94,6 +97,8 @@ export default class Updux<D extends DuxConfig> {
this.#reactions = (duxConfig.reactions as any) ?? [];
this.#actions = buildActions(duxConfig.actions, this.#subduxes) as any;
this.#selectors = duxConfig.selectors ?? {};
}
@ -166,6 +171,17 @@ export default class Updux<D extends DuxConfig> {
throw new Error(`redefining action ${type}`);
}
addSelector<R, N extends string>(name: N, selector: (state: DuxState<D>) => R) {
this.#selectors = {
...this.#selectors,
[name]: selector,
}
return this as any as Updux<D & {
selectors: Record<N, (state: DuxState<D>) => R>
}>;
}
addMutation<A extends keyof DuxActions<D>>(
actionType: A,
mutation: Mutation<
@ -240,7 +256,7 @@ export default class Updux<D extends DuxConfig> {
get selectors(): DuxSelectors<D> {
return this.#memoBuildSelectors(
this.duxConfig.selectors,
this.#selectors,
this.#subduxes,
) as any;
}

View File

@ -19,8 +19,8 @@ describe('basic selectors', () => {
getY: ({ y }: { y: number }) => y,
getYPlus:
({ y }) =>
(incr: number) =>
(y + incr) as number,
(incr: number) =>
(y + incr) as number,
},
}),
// cause the type to fail
@ -51,4 +51,17 @@ describe('basic selectors', () => {
expect(store.getState.getY()).toBe(2);
expect(store.getState.getYPlus(3)).toBe(5);
});
test('addSelector', () => {
const dux = new Updux({ initialState: 13 }).addSelector(
'plusHundred',
(state) => state + 100,
);
expectTypeOf(dux.selectors.plusHundred).toMatchTypeOf<
(state: number) => number
>();
expect(dux.selectors.plusHundred(7)).toBe(107);
});
});