在 TypeScript 中扩展重载方法时出现问题

问题描述 投票:0回答:1

在父类中,我定义了一个具有不同参数的方法:存储中的索引或元素,并且根据参数,我通过索引从存储中获取元素或仅使用给定的元素。
因此,我使用重载来定义这些方法:

class Parent<T> {
  items: T[] = [];
  item: T = {} as T;

  applyMethod(index: number): void;
  applyMethod(item: T): void;
  applyMethod(param: number | T): void {
    if (typeof param === 'number') {
      param = this.items[param];
    }
    this.item = param;
  }
}

class Child1<T> extends Parent<T> {
  // In my application, I actually add an id: string overload.
  override applyMethod(param: number | T): void {
    // Do something more before calling:
    super.applyMethod(param);
  }
}

class Child2<T> extends Parent<T> {
  override applyMethod(param: number | T): void {
    if (typeof param === 'number') {
      super.applyMethod(param);
    } else {
      super.applyMethod(param);
    }
  }
}

也可以在TS Playground看到它。

在 Child1 中,我有一个错误:

No overload matches this call.\
  Overload 1 of 2, '(index: number): void', gave the following error.\
    Argument of type 'number | T' is not assignable to parameter of type 'number'.\
      Type 'T' is not assignable to type 'number'.
  Overload 2 of 2, '(item: T): void', gave the following error.\
    Argument of type 'number | T' is not assignable to parameter of type 'T'.\
      'T' could be instantiated with an arbitrary type which could be unrelated to 'number | T'.(2769

我可以像 Child2 中所示解决它,但这很奇怪/愚蠢。

另一种解决方法是定义

applyMethod(param: any): void {}
而不是
number | T
。这是经典的,这就是我最初所做的,但我发现 TS 只能看到
param: any
参数定义,因此我输了。

我选择了另一种方式,打电话给

super.applyMethod(param as any);
。至少,输入会保留其打字内容。

还有其他更优雅的方式吗?我错过了什么吗?

typescript generics overloading
1个回答
0
投票

正如 jcalz 所建议的,使用重载可能会出现问题。
他们的优点之一是允许根据过载来个性化 JSDoc 注释:

/**
 * Set the active item to the item at the specified index .
 *
 * @param index - The index of the item to be set as active.
 */
setActiveItem(index: number): void;
/**
 * Set the active item to the specified item.
 *
 * @param item - The item to be set as active.
 */
setActiveItem(item: I): void;
setActiveItem(param: number | I): void {
}

一旦删除重载,我必须制作更通用的文档:

/**
 * Set the active item to the given item or the one at the specified index.
 *
 * @param param - The item itself or the index of the item to be set as active.
 */
setActiveItem(param: number | I): void {
}

它至少简化了代码,并且最终更具可读性,所以还可以。

© www.soinside.com 2019 - 2024. All rights reserved.