Coder Social home page Coder Social logo

Comments (1)

Inlustra avatar Inlustra commented on June 25, 2024

I've spent longer on this than I probably should have, but should anyone be interested, I've created the following module to replace the types.

interface Actions<T extends string = string> {
  type: T;
}

declare module 'redux-beacon' {
  export declare type Target = (events: any[]) => void;
  export type EventDefinition<E = any, A extends Actions = any, S = any> = (
    action: A,
    prevState: S,
    nextState: S,
  ) => E;

  type FilterType<T, U> = T extends { type: infer S }
    ? U extends S
      ? T
      : never
    : never;

  type EventMap<A extends { type: string }, S = any> = Partial<
    { [K in A['type']]: EventDefinition<any, FilterType<A, K>, S> | undefined }
  >;
}

declare module '@redux-beacon/combine-events' {
  import { EventDefinition } from 'redux-beacon';

  declare function combineEvents<A extends Actions = any, S = any>(
    ...eventDefs: EventDefinition<any, A, S>[]
  ): (action: A, prevState: S, nextState: S) => any[];

  export default combineEvents;
}

declare module '@redux-beacon/google-analytics-gtag' {
  import { EventDefinition } from 'redux-beacon';
  export declare function trackPageView<A extends Actions = any, S = any>(
    eventDef: EventDefinition<
      {
        title?: string;
        location?: string;
        path?: string;
      },
      A,
      S
    >,
  ): EventDefinition<any, A, S>;

  export declare function trackEvent<A extends Actions = any, S = any>(
    eventDef: EventDefinition<
      {
        category: string;
        action: string;
        label?: string;
        value?: number;
      },
      A,
      S
    >,
  ): EventDefinition<any, A, S>;
}

The benefit of doing this, is that I can now write the following:

export const eventMap: EventMap<Action> = {
    [MY_CUSTOM_ACTION]: trackEvent(action => ({
      action: 'custom action' + action.payload.customProp,
      category: 'engagement',
    })
}

And all of the types are correctly inferred, action is inferred as MyCustomAction using the following module example:

export const MY_CUSTOM_ACTION = 'actionType1'
export type MyCustomAction {
    type: typeof MY_CUSTOM_ACTION,
    payload: {
        customProp: number
    }
} 

export type Action = MyCustomAction | MyCustomAction2... etc

It just means that everything is typed correctly and VSCode will give you some nice help when working out which action type to accept

from redux-beacon.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.