为什么此实现接口的TypeScript类不能分配给扩展该接口的一般约束? [英] Why is this TypeScript class implementing the interface not assignable to a generic constraint extending the interface?

查看:66
本文介绍了为什么此实现接口的TypeScript类不能分配给扩展该接口的一般约束?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

 接口向量{设置(... args:number []):这个;setScalar(标量:数字):this;钳位(min:this,max:this):this;...}Vector2类实现Vector {...}接口矩阵{元素:number [];getRow< Textended Vector>(n:数字):T;...}Matrix2类实现Matrix {private _elements:number [];public getRow(i:number):Vector2 {const te = this._elements;切换(i){案例0:返回新的Vector2(te [0],te [2]);情况1:返回新的Vector2(te [1],te [3]);默认:抛出新的错误('没有行定义在'+ i +'.');}}} 

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

 类型"Matrix2"中的属性"getRow"不能分配给基本类型"Matrix"中的相同属性.输入'(i:number)=>向量2'不能分配给类型'< T扩展向量>(n:数字)=>T'.不能将类型'Vector2'分配给类型'T'.ts(2416) 

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

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

我正在使用TypeScript 3.6.3.

解决方案

我认为这里的问题是可以在呼叫站点指定通用的 T ,但是 m.getRow 始终返回 Vector2 ,无论调用站点为 T 指定什么.

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

  class Vector3扩展了Vector {}const m = new Matrix()const row = m.getRow< Vector3>(0)//您指定了Vector3,但得到了Vector2. 

这里最简单的解决方案是删除泛型,只声明 getRow 以始终返回 Vector :

 接口矩阵{元素:number [];getRow(n:number):向量;} 

I'm trying to develop some interfaces for linear algebra functions, because the world needs another linear algebra library. The (possibly bad) idea is to be able to specify Vector or Matrix for some higher level functions and have it just work, as long as the dimensions are correct.

I ran into some problems doing this with the Vector interface, but I discovered using this as a type and it resolved my issues (maybe I'm doing a bad thing here). I tried doing this in the Matrix interface, but because the arguments to the functions aren't of type Matrix, the this trick doesn't work.

I'm getting this same error for a lot of functions like this, but this is one example:

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 + '.');
    }
  }
}

Constructing the interface this way, I get the following error message:

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 implements the Vector interface, and the generic type constraint on getRow() requires the return type to be a type that implements the Vector interface.

Why I can't do things this way? I don't understand what this message is trying to tell me. I know I could probably work around this, but I also want to understand more about what's going on and maybe learn (!) something.

I'm using TypeScript 3.6.3.

解决方案

I think the problem here is that the generic T can be specified at the call site, but m.getRow always returns a Vector2, no matter what the call site specifies for T.

For example, the following would be valid TypeScript, but doesn't work in your case. To prevent this situation from occurring, TypeScript will not compile and throw an error instead.

class Vector3 extends Vector { }

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

The easiest solution here would be to remove the generic and just declare getRow to always return a Vector:

interface Matrix {
  elements: number[];
  getRow(n: number): Vector;
}

这篇关于为什么此实现接口的TypeScript类不能分配给扩展该接口的一般约束?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆