aikoven / typescript-fsa

Type-safe action creator utilities
MIT License
607 stars 28 forks source link

Feature request: Add optional mapPayload parameter #69

Closed iiroj closed 10 months ago

iiroj commented 6 years ago

I would appreciate the ability to add an optional parameter for mapping the values of an action's payload. This would be useful, for example, for dispatching notifications and assigning them a UUID in the action itself.

My current work-around is the following wrapper function:

import { Action, AnyAction, Meta } from 'typescript-fsa'

// Copy-pasted from typescript-fsa, with Overload edits
type ActionCreator<Payload, Overload = Payload> = {
  type: string
  match: (action: AnyAction) => action is Action<Overload>
  (payload: Payload, meta?: Meta): Action<Overload>
} & (Payload extends void
  ? (payload?: Payload, meta?: Meta) => Action<Overload>
  : {})

function mapActionCreatorPayload<P extends {}, O extends {} = P>(
  actionCreator: ActionCreator<P>,
  mapPayload: (payload: P) => O
) {
  const action = (payload: P): Action<ReturnType<typeof mapPayload>> => ({
    type: actionCreator.type,
    payload: mapPayload(payload)
  })

  const overload = Object.assign(action, {
    type: actionCreator.type,
    match: actionCreator.match
  })

  // Type 'Payload' is not comparable to type 'Overload'
  return (overload as unknown) as ActionCreator<
    P,
    ReturnType<typeof mapPayload>
  >
}

The usage is then:

const actionCreator = actionCreatorFactory('notifications')
const addAction = actionCreator<NotificationWithoutId>('ADD')

export const addNotification = mapActionCreatorPayload(
    addAction,
    (notification): NotificationWithId => ({
      ...notification,
      id: uuid()
    })
  )

This works perfectly in the sense that addNotification doesn't accept and id key in its argument payload (NotificationWithoutId), but the resulting payload in Redux will contain the id (NotificationWithId).

I think this would be an useful optional feature right in TypeScript-FSA.

aikoven commented 5 years ago

Sorry for being quiet for so long.

I'm planning to explore this for 3.0 stable within the next couple of months.

iiroj commented 5 years ago

Thanks @aikoven! Let me know if you require any help or additional feedback on this!