skip to Main Content

I’ve got an app which has a lot of modals. I wrote a fn which maps each modal to open and close fns, so i get syntax like this:

open.modalname(timeout, callback, props)

I’m using react, and in some cases i pass the open fn to onClick callback, which injects an event, which i have no use for, so i have a helper fn which ignores it.

These are the function types i’ve got

export type Output<T extends Object, F> = Record<keyof T, F>;

export type Open = Output<
  typeof modals,
  (
    timeout?: number | React.MouseEvent<HTMLElement> | object,
    callback?: number | (() => void),
    props?: object | (() => void),
    _?: object | (() => void)
  ) => void
>;

export type Close = Output<typeof modals, () => void>;

I’m allowing 2 syntaxes in my helper: (timeout?, callback:?, props?)
or (props?)

Is there a way to write the Open type so i get a nicer autocomplete but allow all the possible types. eg:

(timeout?: number, callback?: () => void, props?: object) | (props?: object)

2

Answers


  1. I genuinely have no idea what you’re trying to accomplish, but if you just want to accept different options per function call, why not just do:

    export interface OpenFn {
      (options?: {
        event?: React.MouseEvent<HTMLElement>,
        timeout?: number,
        callback?: () => void,
        props?: object,
      }): void
    }
    
    const open: OpenFn = (options = {}) => {
      const { 
        event,
        timeout,
        callback, 
        props,
      } = options;
      // logic
      // ...
    }
    
    Login or Signup to reply.
  2. It sounds like you want a function type that essentially has multiple overloads. Since overloads are really intersections of function types, you can use intersections. Do note that function types must be wrapped in parentheses to avoid ambiguity when used in intersections and unions.

    type Open = ((timeout?: number, callback?: () => void, props?: object) => void) & ((props?: object) => void);
    

    However, this can get a little clunky if you have a lot of overloads. Consider switching to call signatures instead of intersections. The syntax is different, but they essentially achieve the same thing here.

    type Open = {
        (timeout?: number, callback?: () => void, props?: object): void;
        (props?: object): void;
    };
    

    Playground (intersections)

    Playground (call signatures)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search