beginning on selectors

This commit is contained in:
Yanick Champoux 2023-03-10 10:31:30 -05:00
parent 3e9049ce93
commit c660b7be1d
2 changed files with 56 additions and 6 deletions

View File

@ -26,10 +26,10 @@ type ResolveAction<
? ActionArg ? ActionArg
: ActionArg extends (...args: any) => any : ActionArg extends (...args: any) => any
? ActionCreatorWithPreparedPayload< ? ActionCreatorWithPreparedPayload<
Parameters<ActionArg>, Parameters<ActionArg>,
ReturnType<ActionArg>, ReturnType<ActionArg>,
ActionType ActionType
> >
: ActionCreatorWithoutPayload<ActionType>; : ActionCreatorWithoutPayload<ActionType>;
type ResolveActions< type ResolveActions<
@ -37,10 +37,10 @@ type ResolveActions<
[key: string]: any; [key: string]: any;
}, },
> = { > = {
[ActionType in keyof A]: ActionType extends string [ActionType in keyof A]: ActionType extends string
? ResolveAction<ActionType, A[ActionType]> ? ResolveAction<ActionType, A[ActionType]>
: never; : never;
}; };
export type Mutation<A extends Action<any> = Action<any>, S = any> = ( export type Mutation<A extends Action<any> = Action<any>, S = any> = (
payload: A extends { payload: A extends {
@ -51,12 +51,22 @@ export type Mutation<A extends Action<any> = Action<any>, S = any> = (
action: A, action: A,
) => (state: S) => S | void; ) => (state: S) => S | void;
export type AggregateSelectors<S> = S;
type SelectorForState<S> = (state: S) => unknown;
type SelectorsForState<S> = {
[key: string]: SelectorForState<S>;
};
export default class Updux< export default class Updux<
T_LocalState = Record<any, any>, T_LocalState = Record<any, any>,
T_LocalActions extends { T_LocalActions extends {
[actionType: string]: any; [actionType: string]: any;
} = {}, } = {},
T_Subduxes extends Record<string, Dux> = {}, T_Subduxes extends Record<string, Dux> = {},
T_LocalSelectors extends SelectorsForState<
AggregateState<T_LocalState, T_Subduxes>
> = {},
> { > {
#localInitial: T_LocalState; #localInitial: T_LocalState;
#localActions: T_LocalActions; #localActions: T_LocalActions;
@ -70,11 +80,19 @@ export default class Updux<
#initial: AggregateState<T_LocalState, T_Subduxes>; #initial: AggregateState<T_LocalState, T_Subduxes>;
#localSelectors: Record<
string,
(state: AggregateState<T_LocalState, T_Subduxes>) => any
>;
#selectors: AggregateSelectors<T_LocalSelectors>;
constructor( constructor(
config: Partial<{ config: Partial<{
initial: T_LocalState; initial: T_LocalState;
actions: T_LocalActions; actions: T_LocalActions;
subduxes: T_Subduxes; subduxes: T_Subduxes;
selectors: T_LocalSelectors;
}>, }>,
) { ) {
// TODO check that we can't alter the initial after the fact // TODO check that we can't alter the initial after the fact
@ -85,6 +103,7 @@ export default class Updux<
this.#actions = buildActions(this.#localActions, this.#subduxes); this.#actions = buildActions(this.#localActions, this.#subduxes);
this.#initial = buildInitial(this.#localInitial, this.#subduxes); this.#initial = buildInitial(this.#localInitial, this.#subduxes);
this.#localSelectors = config.selectors;
} }
get actions() { get actions() {
@ -110,6 +129,10 @@ export default class Updux<
return store; return store;
} }
get selectors(): T_LocalSelectors {
return this.#localSelectors as any;
}
// TODO memoize this sucker // TODO memoize this sucker
get reducer() { get reducer() {
return buildReducer( return buildReducer(

27
src/selectors.test.ts Normal file
View File

@ -0,0 +1,27 @@
import { test, expect } from 'vitest';
import Updux, { createAction } from './index.js';
test('basic selectors', () => {
type State = { x: number };
const foo = new Updux({
initial: {
x: 1,
},
selectors: {
getX: ({ x }: State) => x,
},
subduxes: {
bar: new Updux({
initial: { y: 2 },
selectors: {
getY: ({ y }: { y: number }) => y,
},
}),
},
});
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);
});