selector test is passing
This commit is contained in:
parent
c660b7be1d
commit
7a5733425e
25
src/Updux.ts
25
src/Updux.ts
@ -12,7 +12,7 @@ import {
|
||||
ActionCreatorWithoutPayload,
|
||||
ActionCreatorWithPreparedPayload,
|
||||
} from '@reduxjs/toolkit';
|
||||
import { AggregateActions, Dux } from './types.js';
|
||||
import { AggregateActions, AggregateSelectors, Dux } from './types.js';
|
||||
import { buildActions } from './buildActions.js';
|
||||
import { buildInitial, AggregateState } from './initial.js';
|
||||
import { buildReducer, MutationCase } from './reducer.js';
|
||||
@ -51,8 +51,6 @@ export type Mutation<A extends Action<any> = Action<any>, S = any> = (
|
||||
action: A,
|
||||
) => (state: S) => S | void;
|
||||
|
||||
export type AggregateSelectors<S> = S;
|
||||
|
||||
type SelectorForState<S> = (state: S) => unknown;
|
||||
type SelectorsForState<S> = {
|
||||
[key: string]: SelectorForState<S>;
|
||||
@ -84,8 +82,7 @@ export default class Updux<
|
||||
string,
|
||||
(state: AggregateState<T_LocalState, T_Subduxes>) => any
|
||||
>;
|
||||
|
||||
#selectors: AggregateSelectors<T_LocalSelectors>;
|
||||
#selectors: any;
|
||||
|
||||
constructor(
|
||||
config: Partial<{
|
||||
@ -104,6 +101,16 @@ export default class Updux<
|
||||
|
||||
this.#initial = buildInitial(this.#localInitial, this.#subduxes);
|
||||
this.#localSelectors = config.selectors;
|
||||
|
||||
const basedSelectors = R.mergeAll(
|
||||
Object.entries(this.#subduxes)
|
||||
.filter(([slice, { selectors }]) => selectors)
|
||||
.map(([slice, { selectors }]) =>
|
||||
R.mapValues(selectors, (s) => (state) => s(state[slice])),
|
||||
),
|
||||
);
|
||||
|
||||
this.#selectors = R.merge(basedSelectors, this.#localSelectors);
|
||||
}
|
||||
|
||||
get actions() {
|
||||
@ -129,8 +136,12 @@ export default class Updux<
|
||||
return store;
|
||||
}
|
||||
|
||||
get selectors(): T_LocalSelectors {
|
||||
return this.#localSelectors as any;
|
||||
get selectors(): AggregateSelectors<
|
||||
T_LocalSelectors,
|
||||
T_Subduxes,
|
||||
AggregateState<T_LocalState, T_Subduxes>
|
||||
> {
|
||||
return this.#selectors as any;
|
||||
}
|
||||
|
||||
// TODO memoize this sucker
|
||||
|
@ -22,6 +22,11 @@ test('basic selectors', () => {
|
||||
},
|
||||
});
|
||||
|
||||
expect(foo.selectors.getY({ bar: { y: 3 } } as typeof foo.initial)).toBe(3);
|
||||
expect(foo.selectors.getX({ x: 4 } as typeof foo.initial)).toBe(4);
|
||||
const sample = {
|
||||
x: 4,
|
||||
bar: { y: 3 },
|
||||
};
|
||||
|
||||
expect(foo.selectors.getY(sample)).toBe(3);
|
||||
expect(foo.selectors.getX(sample)).toBe(4);
|
||||
});
|
||||
|
15
src/types.ts
15
src/types.ts
@ -6,6 +6,7 @@ export type Dux<
|
||||
> = Partial<{
|
||||
initial: STATE;
|
||||
actions: ACTIONS;
|
||||
selectors: Record<string, (state: STATE) => any>;
|
||||
reducer: (
|
||||
state: STATE,
|
||||
action: ReturnType<ACTIONS[keyof ACTIONS]>,
|
||||
@ -13,11 +14,25 @@ export type Dux<
|
||||
}>;
|
||||
|
||||
type ActionsOf<DUX> = DUX extends { actions: infer A } ? A : {};
|
||||
type SelectorsOf<DUX> = DUX extends { selectors: infer A } ? A : {};
|
||||
|
||||
export type AggregateActions<A, S> = UnionToIntersection<
|
||||
ActionsOf<S[keyof S]> | A
|
||||
>;
|
||||
|
||||
type BaseSelector<F extends (...args: any) => any, STATE> = (
|
||||
state: STATE,
|
||||
) => ReturnType<F>;
|
||||
|
||||
type BaseSelectors<S, STATE> = {
|
||||
[key in keyof S]: BaseSelector<S[key], STATE>;
|
||||
};
|
||||
|
||||
export type AggregateSelectors<S, SUBS, STATE = {}> = BaseSelectors<
|
||||
UnionToIntersection<SelectorsOf<SUBS[keyof SUBS]> | S>,
|
||||
STATE
|
||||
>;
|
||||
|
||||
export type UnionToIntersection<U> = (
|
||||
U extends any ? (k: U) => void : never
|
||||
) extends (k: infer I) => void
|
||||
|
Loading…
Reference in New Issue
Block a user