Skip to content

Commit 66e4be1

Browse files
committed
fix: improve typings for deps/inject and action payload
1 parent 7f3dc9c commit 66e4be1

File tree

3 files changed

+50
-30
lines changed

3 files changed

+50
-30
lines changed

example/typed/src/components/order/order.model.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ const model = createModel<State, Actions, Deps>({
4343
},
4444
actions: ({ initialState }) => ({
4545
// Basic actions
46-
fooAction: (state, action: { payload: number }) => ({
46+
fooAction: (state, action) => ({
4747
...state,
4848
foo: action.payload,
4949
}),
Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,77 @@
11
declare module 'reducktion' {
2+
// Helper
3+
type ArgumentType<F extends Function> = F extends (arg: infer A) => any
4+
? A
5+
: never;
6+
7+
// TODO: do we need this?
28
interface RootState<StatePart> {
39
[statePart: string]: StatePart;
410
}
5-
11+
612
type Selector<State> = (state: RootState<State>, ...args: any[]) => any;
7-
13+
814
// Provide action keys for auto-complete but allow custom types
915
// that are eg. auto-generated by fetchable action
1016
type ActionTypes<Actions> = { [K in keyof Actions]: string } & {
1117
[x: string]: string;
1218
};
13-
14-
interface ActionCreator<Payload = any> {
19+
20+
interface ActionCreator<Payload> {
1521
type: string;
1622
payload: Payload;
1723
[x: string]: any; // Allow additional meta fields
1824
}
19-
25+
2026
type ActionFunc<Payload = any> = (
2127
payload?: Payload
2228
) => ActionCreator<Payload>;
23-
29+
2430
type Thunk<Deps> = (
2531
arg: any,
2632
deps: Deps
2733
) => (dispatch: any, getState: () => any, ...args: any[]) => Promise<void>;
28-
34+
2935
type Reducer<State, Payload = any> = (
3036
state: State,
3137
action: ActionCreator<Payload>
3238
) => State;
33-
39+
3440
interface FetchableReducers<State> {
3541
loading: Reducer<State>;
3642
success: Reducer<State>;
3743
failure: Reducer<State>;
3844
}
39-
45+
4046
interface Fetchable {
41-
value: <T>(val: T) => FetchableValue<T>,
47+
value: <T>(val: T) => FetchableValue<T>;
4248
action: <State, K extends keyof State>(
4349
// Only allow state fields for fetchable values
4450
stateField: FetchableValue extends State[K] ? K : never,
4551
customReducers?: Partial<FetchableReducers<State>>
46-
) => FetchableReducers<State>,
52+
) => FetchableReducers<State>;
4753
}
48-
54+
4955
interface Dependencies {
5056
[depName: string]: Model<any, any>;
5157
}
52-
58+
5359
// TODO:
5460
// Figure out how to show proper error
5561
// if given action is not in keyof Actions
5662
interface ModelDefinition<State, Actions, Deps> {
5763
name: string;
58-
inject?: string[];
64+
inject?: [keyof Deps];
5965
state: State;
6066
actions: (
6167
{ initialState }: { initialState: State }
6268
) => {
6369
// Only include those keys that are present in the action's interface
64-
[K in keyof Actions]: Reducer<State> | FetchableReducers<State>
70+
[K in keyof Actions]: Actions[K] extends FetchableAction<any>
71+
? FetchableReducers<State>
72+
: Actions[K] extends Function
73+
? Reducer<State, ArgumentType<Actions[K]>>
74+
: never
6575
};
6676
reactions?: (
6777
{ initialState, deps }: { initialState: State; deps: Deps }
@@ -81,7 +91,7 @@ declare module 'reducktion' {
8191
[thunkName: string]: Thunk<Deps>;
8292
};
8393
}
84-
94+
8595
interface Model<State, Actions> {
8696
name: string;
8797
initialState: State;
@@ -95,34 +105,34 @@ declare module 'reducktion' {
95105
getSagas: () => [];
96106
getReducer: () => Reducer<any>;
97107
}
98-
108+
99109
// EXPORTS ********************************************************************
100-
110+
101111
export enum FetchableStatus {
102112
INITIAL,
103113
LOADING,
104114
SUCCESS,
105115
FAILURE,
106116
}
107-
117+
108118
export interface FetchableValue<Data = any> {
109119
data: Data;
110120
error: any;
111121
status: FetchableStatus;
112122
}
113-
123+
114124
export interface FetchableAction<SuccessData> extends ActionFunc {
115125
init: ActionFunc;
116126
fail: ActionFunc;
117127
success: ActionFunc<SuccessData>;
118128
}
119-
129+
120130
export const fetchable: Fetchable;
121-
131+
122132
export function createModel<State, Actions, Deps = Dependencies>(
123133
df: ModelDefinition<State, Actions, Deps>
124134
): Model<State, Actions>;
125-
135+
126136
export function initModels(
127137
models: Model<any, any>[]
128138
): {
@@ -132,5 +142,5 @@ declare module 'reducktion' {
132142
allSagas: any[];
133143
} & {
134144
[modelName: string]: Model<any, any>;
135-
};
145+
};
136146
}

src/reducktion.d.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
// Helper
2+
type ArgumentType<F extends Function> = F extends (arg: infer A) => any
3+
? A
4+
: never;
5+
6+
// TODO: do we need this?
17
interface RootState<StatePart> {
28
[statePart: string]: StatePart;
39
}
@@ -10,7 +16,7 @@ type ActionTypes<Actions> = { [K in keyof Actions]: string } & {
1016
[x: string]: string;
1117
};
1218

13-
interface ActionCreator<Payload = any> {
19+
interface ActionCreator<Payload> {
1420
type: string;
1521
payload: Payload;
1622
[x: string]: any; // Allow additional meta fields
@@ -37,12 +43,12 @@ interface FetchableReducers<State> {
3743
}
3844

3945
interface Fetchable {
40-
value: <T>(val: T) => FetchableValue<T>,
46+
value: <T>(val: T) => FetchableValue<T>;
4147
action: <State, K extends keyof State>(
4248
// Only allow state fields for fetchable values
4349
stateField: FetchableValue extends State[K] ? K : never,
4450
customReducers?: Partial<FetchableReducers<State>>
45-
) => FetchableReducers<State>,
51+
) => FetchableReducers<State>;
4652
}
4753

4854
interface Dependencies {
@@ -54,13 +60,17 @@ interface Dependencies {
5460
// if given action is not in keyof Actions
5561
interface ModelDefinition<State, Actions, Deps> {
5662
name: string;
57-
inject?: string[];
63+
inject?: [keyof Deps];
5864
state: State;
5965
actions: (
6066
{ initialState }: { initialState: State }
6167
) => {
6268
// Only include those keys that are present in the action's interface
63-
[K in keyof Actions]: Reducer<State> | FetchableReducers<State>
69+
[K in keyof Actions]: Actions[K] extends FetchableAction<any>
70+
? FetchableReducers<State>
71+
: Actions[K] extends Function
72+
? Reducer<State, ArgumentType<Actions[K]>>
73+
: never
6474
};
6575
reactions?: (
6676
{ initialState, deps }: { initialState: State; deps: Deps }

0 commit comments

Comments
 (0)