打字稿错误TS2394:重载签名与函数实现不兼容

时间:2017-04-21 09:02:59

标签: typescript

以下是Typecript编译器诅咒的代码:

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

错误TS2394:过载签名与功能实现不兼容。

我无法理解如何正确地执行过载。你能说出挖掘的方向吗?

1 个答案:

答案 0 :(得分:3)

你走了:

注意:发明了PathParamsRequestHandlerRequestHandlerParams的类型,但关键是它们是截然不同且不兼容的

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;
  }
}

请注意,在创建重载定义时,消费者无法使用实现签名。只有没有实现的签名可用。这就是为什么我在你的例子中添加了一个额外的签名。

这样做的原因是,为了使第一个参数“可选”,我们需要给它一个可能的数组元素类型兼容的类型< / em>可能的其余参数类型。

您当然可以将实现签名中的参数类型指定为anyany[],而不会影响您的消费者的类型安全(实现签名不是接口的一部分),但是,通过使用精确,结构良好的联合类型,您可以使用类型保护来区分参数并验证实现是否处理它们。

这意味着您需要在函数实现中通过逻辑确定第一个参数是否实际为PathParams