typescript 泛型函数实现中的自定义类型

pgccezyw  于 2023-03-24  发布在  TypeScript
关注(0)|答案(1)|浏览(159)

我在这个问题上挣扎(我知道我可以用不同的方式重写,我只是想知道它是否可能)传递到接口的通用类型实现中的自定义类型,或者我只能传递原生TS类型(字符串,数字等):

type coordinates = {
  x: string;
  y: string;
};

interface polygon {
  convert<T>(cord: T): string;
}

class triangle implements polygon {
  public cord: coordinates;
  constructor(cord: coordinates) {
    this.cord = cord;
  }
  convert(cord: coordinates): string {
    return "the coordinates is x:" + cord.x + " y:" + cord.y;
  }
}

我使用TypeScript 4.9.5。编辑器在转换的实现中给予了我这个错误:
类型“triangle”中的属性“convert”不能分配给基类型polygon中的同一属性。类型(cord: coordinates) => string不能分配给类型<T>(cord: T) => string。参数“cord”和“cord”的类型不兼容。类型“T”不能分配给类型“coordinates”。

zpgglvta

zpgglvta1#

以下类型

interface Polygon {
  convert<T>(coord: T): string;
}

是一个非泛型类型,带有一个泛型convert方法。对于泛型方法(和一般的泛型函数),caller 指定类型参数。因此Polygon需要允许调用者使用任何他们喜欢的T类型参数调用convert()

function foo(p: Polygon) {
  p.convert(123); // okay
  // (method) Polygon.convert<number>(coord: number): string
  p.convert(new Date()); // okay
  // (method) Polygon.convert<Date>(coord: Date): string
}

这意味着Polygon示例的 * 实现者 * 不允许 * 对T将被指定为什么做出限制性假设。他们需要支持所有可能的T类型。因此以下内容无效:

class Triangle implements Polygon {
  public coord: Coordinates;
  constructor(coord: Coordinates) {
    this.coord = coord;
  }
  convert(coord: Coordinates): string { // error!
    return "the coordinates is x:" +
      coord.x.toUpperCase() + " y:" + coord.y;
  }
}

Triangle类没有正确地实现PolygonTriangleconvert()方法需要一个Coordinates参数,但是Polygon的实现者没有做出这个选择。
我非常怀疑您是否希望Polygon接受任何可能的convert输入。所以您可能会更乐意更改为这个版本:

interface Polygon<T> {
  convert(coord: T): string;
}

这是一个带有 * 非泛型 * 方法的 * 泛型 * 类型。没有更多的类型本身是Polygon;相反,类型是Polygon<T>,当你提到该类型时,你需要指定类型参数T。例如,Polygon<number>有一个{convert(coord: number): string}方法。而Polygon<Coordinates>有一个{convert(coord: Coordinates): string}方法。所以为了实现接口,实现者需要选择T类型参数,然后convert()的调用者别无选择,只能用实现者选择的参数调用它。
现在我们可以看到Triangle确实是一个有效的Polygon<Coordinates>

class Triangle implements Polygon<Coordinates> {
  public coord: Coordinates;
  constructor(coord: Coordinates) {
    this.coord = coord;
  }
  convert(coord: Coordinates): string {
    return "the coordinates is x:" +
      coord.x.toUpperCase() + " y:" + coord.y;
  }
}

如果给你一个Polygon<Coordinates>,那么你就不能再用任意参数调用convert()了:

function foo(p: Polygon<Coordinates>) {
  p.convert(123); // error!
  p.convert(new Date()); // error!
}

Playground代码链接

相关问题