redux-logic icon indicating copy to clipboard operation
redux-logic copied to clipboard

Typescript Examples?

Open Shannor opened this issue 5 years ago • 10 comments

I'm starting to use Typescript in a project and I've used Redux-logic in pretty much all my previous projects. With Typescript though it's been a challenge. I haven't seen that many examples, so I was wondering if there are some can we get them into the docs?

I've only seen one example which isn't even the simplest case. I'm going to keep trying to figure out how it wants things structured in the meantime and make a PR with some examples if its cool.

Shannor avatar Nov 19 '18 03:11 Shannor

I'll flag this as help wanted, maybe some of the folks using Typescript could volunteer some examples.

jeffbski avatar Jan 19 '19 21:01 jeffbski

I've been still working with it and thank I could possibly help provide examples if that is desired? Just point me to the best way to provide them and you can decide if they are helpful.

Shannor avatar Jan 19 '19 23:01 Shannor

Hey @jeffbski any update on this or ways that I can contribute examples? I want to help out as I love using this library over the others out there!

Shannor avatar Mar 19 '19 15:03 Shannor

@jeffbski @Shannor I can look into this. Will provide pull request for review when done.

thachp avatar Apr 22 '19 21:04 thachp

Almost one year later, there are still no typescript examples. I have troubles with action payload in createLogic, the very same issue that @Shannor ~has~ had. @alvis did a great job in typing but the only workaround I've found was to use type guards and now finally it breaks in the createLogicMiddleware. I saw that @alvis redux-logic fork is 2 commits ahead and 86 commits behind. I want to test the impact of c2a79335f44533d9d39448362d79ee863b19bab1 because it seems that this commit lifted the strictness of payload checks and was not included in @alvis's PRs back then. I am not claiming any IP but if the aforementioned commit works for me, I'll create a PR unless @alvis does it for his commit (and maybe the previous one to that).

tafaust avatar Feb 22 '20 09:02 tafaust

Got an extremely narrow and whacky solution right now with the latest commits from alvis... it might be that my action types definition is incompatible with redux-logic. :/

I do follow the official redux typescript docs though... and create my actions as follows:

// types.ts
import { Action } from 'redux';
// […]
export const DEVICE_CONNECT_REQUEST = 'DEVICE_CONNECT_REQUEST';
// […]
interface DeviceConnectAction extends Action {
    type: typeof DEVICE_CONNECT_REQUEST;
    payload: {
        idVendor: number | string;
        idProduct: number | string;
    };
}
// […]
export type DeviceConnectionType = 
    | DeviceConnectAction
    | ...

and

// logic.ts
import * as types from './types';
// helper
type ActionExtractor<C> = Extract<types.DeviceConnectionType, { type: C }>;

type T = T_CONNECT | T_DISCONNECT;
type P = P_CONNECT | P_DISCONNECT;

type T_CONNECT = ActionExtractor<typeof types.DEVICE_CONNECT_REQUEST>['type'];
type P_CONNECT = ActionExtractor<typeof types.DEVICE_CONNECT_REQUEST>['payload'];
const deviceConnectLogic = createLogic<{}, { action: Action<T, P> }>({
    type: types.DEVICE_CONNECT_REQUEST,
    cancelType: types.DEVICE_CONNECT_CANCEL,
    latest: true,

    process(
        { action }: { action: Action<T_CONNECT, P_CONNECT> },
        dispatch: (connectAction: types.DeviceDisConnectType) => void,
        done: () => void,
    ) {
        // we need to cast the payload type here because we did not extend Action from redux-logic here
        const { idVendor, idProduct } = <P_CONNECT>action.payload;
        // tell the service to connect device with { idVendor, idProduct }
        DeviceService.connectDevice(idVendor, idProduct)
            .then(() => {
                dispatch(connectDeviceSuccess());
            })
            .catch((reason: string) => {
                dispatch(connectDeviceFailure(reason));
            })
            .finally(() => {
                done();
            });
    },
});
// Disconnect code analogous to the Connect code

I'll try to investigate further and as soon as I'm ready to publish my repo with redux-logic ts code, I'll link it here.

tafaust avatar Feb 22 '20 12:02 tafaust

Thanks @tahesse that will be very helpful.

jeffbski avatar Feb 25 '20 16:02 jeffbski

@tahesse any updates on this?

TobiasPr avatar Apr 18 '20 20:04 TobiasPr

@TobiasPr I am still at it but had major delays because there was too much stress with other things. Thanks for pinging me, I'll pick up the issue (once again) and report my findings (in whatever form that might be).


EDIT 1 Sorry, my electron code base is currently broken and I need to fix it first before I can continue to test this and provide you guys with an "how I did it" code example.


EDIT 2 Might take a while... my harfbuzz lib is too new (I'm using arch btw :stuck_out_tongue:) for electron and my whole code runs in the electron app... waiting for them to recompile towards the newest harfbuzz so...

tafaust avatar May 02 '20 13:05 tafaust

Here's a solution for redux-logic 3.0.3, using Redux Toolkit's action creators.

Given an action creator like this:

export const uploadData = createAction<{ alwaysNotify?: boolean }>('uploadData');

The redux-logic handler should be able to access the payload like this:

export const uploadRunsLogic = createLogic<RootState, ReturnType<typeof uploadData>['payload']>({
  type: uploadData.type,
  latest: true,

  async process({ getState, action }, dispatch, done) {
    const { alwaysNotify } = action.payload;

joshkel avatar Apr 22 '21 18:04 joshkel