beginning on selectors
This commit is contained in:
parent
3e9049ce93
commit
c660b7be1d
35
src/Updux.ts
35
src/Updux.ts
@ -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
27
src/selectors.test.ts
Normal 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);
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user