Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript error TS2394: Overload signature is not compatible with function implementation

Tags:

typescript

Here is the code that the Typecript compiler curses:

use(path: PathParams, ...handlers: RequestHandler[]): this
use(path: PathParams, ...handlers: RequestHandlerParams[]): this
use(...handlers: RequestHandler[]): this
use(...handlers: RequestHandlerParams[]): this {
    // ...
    return this;
}

error TS2394: Overload signature is not compatible with function implementation.

I can not understand how I can properly do the overload. Can you tell which direction to dig?

like image 710
Khusamov Sukhrob Avatar asked Apr 21 '17 09:04

Khusamov Sukhrob


1 Answers

Here you go:

Note: that the types of PathParams, RequestHandler, and RequestHandlerParams are invented but the point is that they are distinct and incompatible

export interface PathParams {
  path: string;
  params: {
    id: number,
    [key: string]: string | number
  }
}

export type RequestHandler = (request: RequestHandlerParams) => void;

export interface RequestHandlerParams {
  kind: 'query' | 'route'
  value: string;
}

export default class {
  use(path: PathParams, ...handlers: RequestHandler[]): this
  use(path: PathParams, ...handlers: RequestHandlerParams[]): this
  use(...handlers: RequestHandler[]): this
  use(...handlers: RequestHandlerParams[]): this;
  use(
    pathOrHandlerOrHandlerParam: PathParams | RequestHandler | RequestHandlerParams,
    ...handlers: Array<RequestHandler | RequestHandlerParams>
  ): this {
    // ...
    return this;
  }
}

Note that when creating an overload definition, the implementation signature is not available to consumers. Only the signatures that do not have an implementation are available. This is why I have added an additional signature to your example.

The reason why this works is that, in order to make the first parameter "optional" we need to give it a type that may be compatible with the array element type of either of the possible rest parameter types.

You could of course specify the parameter types in the implementation signature as any and any[] without compromising type safety for your consumers (the implementation signature is not part of the interface) but, by using a precise, well-structured union type, you can use type guards to discriminate over the arguments and verify that the implementation handles them.

This implies that you will need to determine if the first parameter is actually a PathParams via logic in the function implementation.

like image 162
Aluan Haddad Avatar answered Oct 13 '22 23:10

Aluan Haddad