Search code examples
typescriptoverloadingtypescript-typings

Method overloading of Higher-order function


The goal is to use method overloading to build a developer friendly SDK. The serviceType argument works fine, but the onMessage argument does not work. Is this just not supported by TypeScript? If so, is there a workaround?

type SwitchMessage = {
  propA: string;
};

type OutletMessage = {
  propB: string;
};

type ServiceType = "Switch" | "Outlet";
type ServiceMessage = SwitchMessage | OutletMessage;

class Client {
  subscribe(serviceType: "Switch", onMessage: (msg: SwitchMessage) => void);
  subscribe(serviceType: "Outlet", onMessage: (msg: OutletMessage) => void);
  subscribe(serviceType: ServiceType, onMessage: (msg: ServiceMessage) => void) {
    console.log("Hello")
  }
}

The message from the compile:

This overload signature is not compatible with its implementation signature.

Solution

  • | works on function arguments in the opposite way you then you think

    Playground

    type SwitchMessage = {
      propA: string;
    };
    
    type OutletMessage = {
      propB: string;
    };
    
    type ServiceType = "Switch" | "Outlet";
    type ServiceMessage = SwitchMessage | OutletMessage;
    
    class Client {
      subscribe(serviceType: "Switch", onMessage: (msg: SwitchMessage) => void): void;
      subscribe(serviceType: "Outlet", onMessage: (msg: OutletMessage) => void): void;
      subscribe(serviceType: ServiceType, onMessage: (msg: SwitchMessage & OutletMessage) => void) {
        console.log("Hello")
      }
      
      subscribe2(serviceType: "Switch", onMessage: (msg: SwitchMessage) => void): void;
      subscribe2(serviceType: "Outlet", onMessage: (msg: OutletMessage) => void): void;
      subscribe2(serviceType: ServiceType, onMessage: ((msg: SwitchMessage) => void) | ((msg: OutletMessage) => void)) {
        console.log("Hello")
      }
    }