export const onPending = ( type , delimiter = '_' ) => `${ type }${ delimiter }PENDING` ; export const onFulfilled = ( type , delimiter = '_' ) => `${ type }${ delimiter }FULFILLED` ; export const onRejected = ( type , delimiter = '_' ) => `${ type }${ delimiter }REJECTED` ; export type Action < Type extends string , Payload = undefined , Meta = undefined > = Payload extends undefined ? Meta extends undefined ? { type : Type ; } : { type : Type ; meta : Meta ; } : Payload extends Error ? Meta extends undefined ? { type : Type ; payload : Payload ; error : true ; } : { type : Type ; payload : Payload ; meta : Meta ; error : true ; } : Meta extends undefined ? { type : Type ; payload : Payload ; } : { type : Type ; payload : Payload ; meta : Meta ; } ; export type AnyAction = Action < string > ; export type ActionCreator < T extends AnyAction , U extends any [ ] = any > = { ( ... args ) : T ; toString ( ) : T [ 'type' ] ; } ; export function createAction < Type extends string > ( type ) ; export function createAction < Type extends string , Payload , U extends any [ ] > ( type , payloadCreator ) ; export function createAction < Type extends string , Payload , Metadata , U extends any [ ] > ( type , payloadCreator , metadataCreator ? ) ; param type example export function createAction < Type extends string , Payload , Metadata , U extends any [ ] > ( type , payloadCreator ? , metadataCreator ? ) { return Object . assign ( ( ... args ) => ( { type , ... ( payloadCreator && { payload : payloadCreator ( ... args ) } ) , ... ( metadataCreator && { meta : metadataCreator ( ... args ) } ) , } ) , { toString : ( ) => type } ) ; } export interface AsyncActionCreator < Type extends string , Payload , Metadata > extends ActionCreator < Action < Type , Promise < Payload > , Metadata > > { pending : ActionCreator < Action < string > > ; fulfilled : ActionCreator < Action < string , Payload > > ; rejected : ActionCreator < Action < string , Error > > ; } param type example export function createAsyncAction < Type extends string , Payload , Metadata , U extends any [ ] > ( type , payloadCreator , metadataCreator ? , { promiseTypeDelimiter : delimiter , } = { } ) { return Object . assign ( createAction ( type , payloadCreator , metadataCreator ) , { toString : ( ) => { throw new Error ( `Async action ${ type } must be handled with pending, fulfilled or rejected` ) ; } , } , { pending : createAction ( onPending ( type , delimiter ) ) , fulfilled : createAction ( onFulfilled ( type , delimiter ) , ( payload ) => payload ) , rejected : createAction ( onRejected ( type , delimiter ) , ( payload ) => payload ) , } ) ; }