问题
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.
回答1:
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;
}
来源:https://stackoverflow.com/questions/57927538/why-is-this-typescript-class-implementing-the-interface-not-assignable-to-a-gene