Closed LouizFC closed 5 years ago
Sorry, I don't understand the topic. Can you explain more? or maybe reproduce it with codesandbox or whatever.
UPDATE: Whooops, the main comment was not loaded for me at that moment :|
@thebrodmann Sorry, I have pressed Enter by accident when typing the title
For completeness, here is the ParamTableActionCreators
export function createParamActionCreators(paramTableName: string) {
return {
addParam: createActionCreator(
`[${paramTableName}] ADD_PARAM`,
(resolve) => (param: Param) => resolve(param)
),
removeParam: createActionCreator(
`[${paramTableName}] REMOVE_PARAM`,
(resolve) => (index: number, param: Param) => resolve({ index, param })
),
updateParam: createActionCreator(
`[${paramTableName}] UPDATE_PARAM`,
(resolve) => (index: number, param: Param) => resolve({ index, param })
),
reorderParams: createActionCreator(
`[${paramTableName}] REORDER_PARAMS`,
(resolve) => (fromIndex: number, toIndex: number) =>
resolve({ fromIndex, toIndex })
),
};
}
type ParamTableActionCreators = ReturnType<typeof createParamActionCreators>;
Reducer<DeepImmutableArray | undefined, ...> is not assignable to Reducer<DeepImmutableArray, ...>
I think the problem is the difference in types between acceptable reducer of the target method and which you are giving to it. I don't think it is because of not using type helper in createReducer return type.
I understand. But what I mean is: The type given by deox/dist/types/Reducer
is not compatible with createReducer
return type.
I have made no further transformations as you can see, yet I am having a compile time error at return normalizeReducer(deoxReducer);
.
I will make some tests to try to prove my argument, maybe I am overthinking something.
I think I found the cuprit:
// createReducer
export declare function createReducer<State, HM extends HandlerMap<State, any>>(
defaultState: State,
handlerMapsCreator: (handle: CreateHandlerMap<State>) => HM[]
): (
state: DeepImmutable<State> | undefined,
action: HM extends HandlerMap<State, infer T> ? T : never
) => State | DeepImmutable<State>;
//redux
export type Reducer<S = any, A extends Action = AnyAction> = (
state: S | undefined,
action: A
) => S
// deox/dist/types/Reducer
export declare type Reducer<State, Actions> = (
prevState: DeepImmutable<State>, // < needs to be DeepImmutable<State> | undefined
action: Actions
) => DeepImmutable<State> | State;
You're right.
Actually, Deox's Reducer
type was used in handleAction
which never call with an undefined
state.
Have you any suggestion to handle this situation?
On the top of my mind, you could do this:
export declare type CreateHandlerMap<State> = <
AC extends ActionCreator<string>,
Actions extends AnyAction = AC extends (...args: any[]) => infer T ? T : never
>(
actionCreators: AC | AC[],
handler: HandlerReducer<State, Actions> // < change here
) => HandlerMap<State, Actions>;
And on deox/types:
export declare type HandlerReducer<State, Actions> = (
prevState: DeepImmutable<State>,
action: Actions
) => DeepImmutable<State> | State;
/* maintain the old Reducer export for backward compatibility maybe?
* if that is not a concern, DeoxReducer could be renamed to just Reducer */
export declare type Reducer<State, Actions> = HandlerReducer<State, Actions>
export declare type DeoxReducer<State, Actions> = (
prevState: DeepImmutable<State> | undefined,
action: Actions
) => DeepImmutable<State> | State;
I agree. Handler
and Reducer
types should be separate as Handler
always gives non- undefined
state but Reducer
can give undefined
state.
I don't think there is a need for backward compatibility, because Reducer
type does not present in public API.
I have a question that is kinda offtopic but related to this.
If we were to make the return type of createReducer
explicit using the DeoxReducer
above, how would be it declared?
In DeoxReducer<State, Action>
The State
type is obvious, but I am having some trouble wrapping my head around the Action
type, because it extracts the action of each of the HandlerMap
s
How can I express this type in the return type?
If we were to make the return type of createReducer explicit using the DeoxReducer above, how would be it declared?
It should be declared like how Action type was declared. By inferring the return type of HandlerMap
(s).
type HandlerMap<TPrevState, TAction, TNextState extends TPrevState> = {
[type in TAction['type']]: Handler<TPrevState, TAction, TNextState>
}
export type InferActionFromHandlerMap<
THandlerMap extends HandlerMap<any, any, any>
> = THandlerMap extends HandlerMap<any, infer T, any> ? T : never
export type InferNextStateFromHandleMap<
THandlerMap extends HandlerMap<any, any, any>
> = THandlerMap extends HandlerMap<any, any, infer T> ? T : never
function createReducer<
TPrevState,
THandlerMap extends HandlerMap<TPRevState, any, any>
>(
defaultState: TPrevState,
handlerMapsCreator: (handle: CreateHandlerMap<TPrevState>) => THandlerMap[]
) {
// ...
return (
state = defaultState,
action: InferActionFromHandlerMap<THandlerMap>
): InferNextStateFromHandleMap<THandlerMap> => {
// ...
}
}
I hope I understood your question correctly. If not, excuse me for my bad English and please ask your question with more details.
That is exactly what I was looking for. I am not a "typescript expert" so I have not yet understood the infer
keyword completely.
Your example made it clear in my mind, Thank you very much
@LouizFC Are you interested to work on this issue?
@thebrodmann I could work in this issue this weekend, but I am not sure exactly what should I do.
Renaming the current Reducer to HandlerReducer and adding a new Reducer with the undefined
fix would be sufficient? I could also try to make the return type of createReducer
explicit
What do you think should be done?
Renaming the current Reducer to HandlerReducer and adding a new Reducer with the undefined fix would be sufficient?
Yes. I suggest the name Handler
instead of HandlerReducer
. Also, HandlerMap
, CreateHandlerMap
and createHandlerMap
uses the current Reducer
type (future Handler
). So those should use Handler
instead of Reducer
.
I could also try to make the return type of
createReducer
explicit.
I will do it on #55.
Also, I suggest you fork a branch from the next branch and work on it due to the huge refactor in b350de45193a79c65b98fe0075f89a2f529ba23d.
So, I will assign this issue to you. Thank you.
@thebrodmann I am having a problem while pushing the changes.
Test Suites: 6 passed, 6 total
Tests: 202 passed, 202 total
Snapshots: 6 obsolete, 6 written, 95 passed, 101 total
Time: 27.952s
Ran all test suites.
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! deox@1.4.0 test-dts: `jest -c dts-jest.config.js "--bail"`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the deox@1.4.0 test-dts script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\User\AppData\Roaming\npm-cache\_logs\2019-06-04T19_47_36_896Z-debug.log
husky > pre-push hook failed (add --no-verify to bypass)
error: failed to push some refs to 'https://github.com/LouizFC/deox.git'
Edit: I tried using the "--updateSnapshot" flag, but the problem persists
Let's try git push
with --no-verify
flag to skip the hook.
This issue has been solved. Thanks to @LouizFC.
For those who received a incomplete issue in email, I am sorry, I have hit enter accidentally before finishing.
Now, to the issue:
I am trying to pass a Reducer as a parameter to a method, but I get a compile error about the types.
Please let me know if I am using the library wrong:
Why doesn't "createReducer" uses the existing Reducer type as a returnType?