为什么实现接口的这种TypeScript类不能分配给扩展接口的通用约束?

时间:2019-09-13 16:49:29

标签: typescript class interface

我正在尝试为线性代数函数开发一些接口,因为世界需要另一个线性代数库。 (可能很糟糕)的想法是,只要尺寸正确,就可以为某些更高级别的功能指定VectorMatrix并使其正常工作。

在使用Vector界面执行此操作时遇到了一些问题,但是我发现使用this作为一种类型,它解决了我的问题(也许我在这里做得不好)。我尝试在Matrix界面中执行此操作,但是由于函数的参数不是Matrix类型,因此this技巧不起作用。

对于许多类似的功能,我也遇到相同的错误,但这是一个示例:

interface Vector {
  set (...args: number[]): this;
  setScalar (scalar: number): this;
  clamp (min: this, max: this): this;
  ...
}

class Vector2 implements Vector { ... }

interface Matrix {
  elements: number[];
  getRow<T extends Vector> (n: number): T;
  ...
}

class Matrix2 implements Matrix {
  private _elements: number[];
  public getRow (i: number): Vector2 {
    const te = this._elements;
    switch (i) {
      case 0:
        return new Vector2(te[0], te[2]);
      case 1:
        return new Vector2(te[1], te[3]);
      default:
        throw new Error('No row defined at ' + i + '.');
    }
  }
}

以这种方式构造接口时,出现以下错误消息:

Property 'getRow' in type 'Matrix2' is not assignable to the same property in base type 'Matrix'.
  Type '(i: number) => Vector2' is not assignable to type '<T extends Vector>(n: number) => T'.
    Type 'Vector2' is not assignable to type 'T'.ts(2416)

Vector2实现Vector接口,getRow()上的通用类型约束要求返回类型必须是实现Vector接口的类型。

为什么我不能这样做?我不明白此消息试图告诉我什么。我知道我可能可以解决此问题,但我也想更多地了解正在发生的事情,也许还可以学习(!)某些东西。

我正在使用TypeScript 3.6.3。

1 个答案:

答案 0 :(得分:0)

我认为这里的问题是可以在呼叫站点上指定通用T,但是无论呼叫站点为{{ 1}}。

例如,以下内容将是有效的TypeScript,但不适用于您的情况。为了防止这种情况的发生,TypeScript不会编译并引发错误。

m.getRow

这里最简单的解决方案是删除泛型,只声明Vector2总是返回T

class Vector3 extends Vector { }

const m = new Matrix()
const row = m.getRow<Vector3>(0) // You specify a Vector3, but get a Vector2.