analytics icon indicating copy to clipboard operation
analytics copied to clipboard

TypeScript types for plugins have very unspecific types

Open dobesv opened this issue 3 years ago • 1 comments

Currently when implementing a plugin, the interface you are implementing is very unspecific about the types:

interface AnalyticsPluginBase {
      name: string;
      EVENTS?: any;
      config?: any;
      initialize?: (...params: any[]) => any;
      page?: (...params: any[]) => any;
      track?: (...params: any[]) => any;
      identify?: (...params: any[]) => any;
      loaded?: (...params: any[]) => any;
      ready?: (...params: any[]) => any;
  }

It would be great to have the specific types here to make implementing plugins easier so we know what the types are.

dobesv avatar Oct 07 '22 19:10 dobesv

If it can help someone, here is my solution to have a better TS support inside plugins.

// utils.ts

interface AnalyticsFuncProps<C extends object> {
  abort: (message: string) => {};
  config: C;
  instance: any;
  plugins: any;
}

interface PayloadProps<T extends 'page' | 'track' | 'identify'> {
  anonymousId: string;
  meta: any;
  options: any;
  type: T;
  userId: string | null;
}

interface InitializeFuncProps<C extends object = {}> extends AnalyticsFuncProps<C> {
  payload: {
    disabled: any[];
    meta: any;
    plugins: string[];
    type: 'initialize';
  };
}

interface PageFuncProps<C extends object = {}> extends AnalyticsFuncProps<C> {
  payload: PayloadProps<'page'>;
}

interface TrackFuncProps<C extends object = {}> extends AnalyticsFuncProps<C> {
  payload: PayloadProps<'track'>;
}

interface IdentifyFuncProps<C extends object = {}> extends AnalyticsFuncProps<C> {
  payload: PayloadProps<'identify'> & {
    traits: Record<string, unknown>;
  };
}

export interface AnalyticsPlugin<C extends object = {}> extends LibAnalyticsPlugin {
  name: string;
  config?: C;
  initializeStart?: (props: InitializeFuncProps<C>) => void;
  initialize?: (props: InitializeFuncProps<C>) => void;
  pageStart?: (props: PageFuncProps<C>) => void;
  page?: (props: PageFuncProps<C>) => void;
  trackStart?: (props: TrackFuncProps<C>) => void;
  track?: (props: TrackFuncProps<C>) => void;
  identify?: (props: IdentifyFuncProps<C>) => void;
  loaded?: () => boolean;
}
// custom-plugin.ts

export function customPlugin(settings: { myPluginSetting: string }, hasUserOptIn: boolean | undefined) {
  const configuration = { ...settings, hasUserOptIn };
  
  return {
    name: "analytics-plugin-custom",
    config: configuration,
    initialize: ({ config }) => {
      // ...
    },
    identify: ({ payload: { userId } }) => {
      // ...
    },
    page: ({ payload: { context } }) => {
      // ...
    },
    track: ({ payload: { event, context, properties } }) => {
      // ...
    },
    reset: () => {
      // ...
    },
    loaded: () => true,
  } satisfies AnalyticsPlugin<typeof configuration>;
}

davidesigner avatar Nov 24 '24 17:11 davidesigner