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

Add ability to add prefix to action names (without updating string literal types) #167

Open rifler opened 5 years ago

rifler commented 5 years ago

Is your feature request related to a real problem or use-case?

With this feature it will be a bit easier to implement ducks in redux https://github.com/erikras/ducks-modular-redux

Describe a solution including usage in code example

function createTableFeature(name: string) {
    const actions = createAsyncAction(
        'table/LOAD_REQUEST',
        'table/LOAD_SUCCESS',
        'table/LOAD_FAILURE',
    )<RequestOptions, Result, HTTPError>({ prefix: name });
    // actions.request() // { type: `${name}table/LOAD_REQUEST` }
    // ....
    return {
        actions,
        reducers: ...,
        epics: ....,
    };
}

Who does this impact? Who is this for?

Now I have to use two filter calls in epic:

// BTW .map doesn't work for createAsyncAction
// so I use createStandardAction
function createTableFeature(name: string) {
    const fetchCampaignsRequest = createStandardAction(
        'table/LOAD_REQUEST',
    ).map((payload: RequestOptions) => ({
        payload: { ...payload, name },
    }));
    // ....
    return {
        actions,
        filterActionByName: (action: AnyAction) =>
         action.payload && action.payload.name
             ? action.payload.name === name
             : true,
        reducers: ...,
        epics: ....,
    };
};

// epics.ts
action$.pipe(
    filter(isActionOf(actions.request)),
    filter(filterActionByName),
    ...
)

Describe alternatives you've considered (optional)

Additional context (optional)

example from redux-act:

const addTodo = createAction('Add todo');
addTodo('content');
// return { type: '[1] Add todo', payload: 'content' }
// so redux-act adds prefix [1]
piotrwitek commented 5 years ago

If prefix is supposed to update the resulting action type it's not trivial task and will require some complex type magic. There are some existing third-party solutions available although I'm not sure about their performance scalability.

rifler commented 5 years ago

It would be great for my tasks to have different prefixes in runtime only

piotrwitek commented 5 years ago

@rifler ok I guess that would be quite easy to implement and could be the first step before investigating and implementing a more complex solution involving a generation of new types.

I will include this into the new API design coming for v5.0.0 #143

DamodarSojka commented 5 years ago

I am not sure what do you mean by "without types support" but this might work for you:

export const createAsyncActionNamed = <T1, T2, T3 = Error, T4 = any>(prefix: string) => createAsyncAction(${prefix}_REQUEST, ${prefix}_SUCCESS, ${prefix}_FAILURE, ${prefix}_CANCEL)<T1, T2, T3, T4>();

The action names are not properly typed.

piotrwitek commented 5 years ago

@DamodarSojka it means without updating string literal types, I have updated the title

piotrwitek commented 4 years ago

It will be soon possible to fully implement this feature with complete type-safety, something I've been waiting for for a long time.

microsoft/TypeScript#40336