piotrwitek / typesafe-actions

Typesafe utilities for "action-creators" in Redux / Flux Architecture
https://codesandbox.io/s/github/piotrwitek/typesafe-actions/tree/master/codesandbox
MIT License
2.41k stars 99 forks source link

Documentation for polymorphic action #252

Open kylegoetz opened 3 years ago

kylegoetz commented 3 years ago

I suggest there be documentation for how to handle a polymorphic action (like one action that could modify N properties of a state with varying property types instead of having N actions, each for changing one property)

suppose I have state

interface Foo {
  bar: string
  baz: number
  // 100 other properties
}

I want an action called setFooProperty that will take <K extends keyof Foo>(key:K, value: Foo[K]) => ...

Typing this is no problem. Either

<K extends ...>() => createAction('DESCRIPTION')<{key:K, value:Foo[K]}>()`

or

createAction('DESCRIPTION', action => <K extends ...>(key:K, newVal: Foo[K]) => action({key,value:newVal})

The problem arises when I rely on the type inference:

const actions = { /* some other actions */, setFooProperty }
type Action = ActionType<typeof actions>

const reducer = (state:Foo, action:Action) => {
  switch(action.type) {
    case getType(setFooProperty):
    // ...
  }
}

With the latter, type inference error

Property 'type' is missing in type '(action: any) => PayloadAction<DESCRIPTION, <K extends  ...>(key: K, newVal: Foo[K]) => any>' but required in type 'Action<string>'

With the former, of course I get a type error that an action factory k => createAction(...) does not match the required type payload => PayloadAction

Assuming there is a way to accomplish this, I suggest it be in the documentation. If it's not possible and instead I need to write N different actions for modifying each property of Foo, then so be it. Just trying to simplify code when it's a simple update.