-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
createReducer does not infer action types #260
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I don't think That's actually half the point of Is there a reason you're calling |
@Glinkis you could do this: const increment = createAction('counter/increment', (n: number) => ({ payload: n }))
const decrement = createAction('counter/decrement', (n: number) => ({ payload: { n } }))
const counterReducer = createReducer(0, {
[increment.type]: (state, action: ReturnType<typeof increment>) => state + action.payload,
[decrement.type]: (state, action: ReturnType<typeof decrement>) => state - action.payload.n,
}) |
Or, just use const counterSlice = createSlice({
name: "counter",
initialState: 0,
reducers: {
increment: (state, action: PayloadAction<number>) => state + action.payload
}
}) |
I will probably end up using
|
@phryneas , any thoughts? |
@Glinkis You're essentially right, to get type inference for Building on the idea of @eddyw , you could do something like this though: function withPayloadType<T>(){
return (t:T) => ({payload: t})
}
const x = createAction('test', withPayloadType<string>()) Would that work for you? @markerikson we could add this as an example of an alternative way to invoke |
Oh, and as far as But that actually doesn't seem to be working - so I'll guess we'll have to at least fix that (@markerikson , your thoughts?) const myReducer = createReducer(0, {
// this is correct
increment(state, action: {type: "increment"}){},
// this should error, but doesn't
decrement(state, action: {type: "foo"}){}
}) |
On second thought, this could be another application of the API I suggested here for |
On a similar thing, with const counterSlice = createSlice({
initialState: 0,
name: 'counter',
reducers: {
decrement: {
prepare: (value: number) => ({ payload: value }),
reducer: (state, action) => { }, << // action is "any" even though it has 'prepare'
},
}
})
I don't think it'd be possible for type InferActionType<N extends string, T extends string> = N + '/' + T 🙈 What I currently have with Redux is a I need this because there is a middleware function which looks like: // action is -> action: ActionTypes
switch (action.type)
case SOME_ACTION:
action.payload <<< correctly inferred based on `action.type`
... However, with |
Yes, I've looked into this extensively a few times, and it is indeed currently impossible to concatenate string types. For the slice, wouldn't it be possible to do something like interface SliceAction<S extends string> extends Action {
slice: S // the slice name
} And then use the additional |
It might, as long as the rest of the type safety works from this. function createPayloadAction<T extends string>(type: T) {
// should also be able to take a "prepareAction" without much effort.
return <P>() => createAction<P, T>(type)
}
const action = createPayloadAction("action")<string>() |
Just a suggestion, don't know if it'd be the best way of doing it:
This could help, maybe. I also have a lazily created slice, for example, that'd look (more or less) like: const createCounter = (name: string, initialState: any) => createSlice({
name,
initialState,
reducers: { ... }
}) This is because I'd like to have composable reducers that are not aware of const counter1 = createCounter('counter1')
const counter2 = createCounter('counter2') If lazily creating reducer with
|
@eddyw you can do this using if (slice.actions.increment.match(action)){
// payload is typed correctly in here
} else if (slice.actions.decrement.match(action)){
// payload is typed correctly in here
} |
Given the weirdness of JS's switch(true) {
case increment.match(action.type) {}
case decrement.match(action.type) {}
} |
You can, but it might be a bit too clever. If/else ishould be more idiomatic in that case. |
Okay, I just opened #262 - would that notation be an improvement for you? |
Fixed by #262 and out in https://github.com/reduxjs/redux-toolkit/releases/tag/v1.1.0 . |
When I create a reducer, the action type does not get inferred from the action.
Example:
I am currently rolling my own setup, where I've got this type of inference working.
Though I'm using the payload rather than the whole action object as a parameter for my callbacks.
In my case, I have to type the action like this through an extra function invocation, though I'm not sure how necessary this is.
I don't pretend to understand how all of this works, but maybe someone can figure out a way to get the best of both worlds? What follows is pretty much my whole setup for this.
The text was updated successfully, but these errors were encountered: