此TypeScript代码:
class Foo {}
function bar<T extends Foo>(): void {
let value: T = new Foo();
}
给出了这个错误:
foo.ts(4,7): error TS2322: Type 'Foo' is not assignable to type 'T'.
这似乎对我不对:T
从Foo
延伸,因此Foo
应该与T
兼容
为什么会发生此错误?
作为使用T extends Foo
在某些情况下正常工作的证据,这是另一个不会出现类型错误的示例:
class Foo {
protected _foo: number;
getFoo(): number {
return this._foo;
}
}
class Bar extends Foo {
protected _bar: number;
}
function bar<T extends Foo>(a: T) {
return a.getFoo();
}
bar(new Foo());
bar(new Bar());
请注意,bar
函数无法访问Bar
上的任何属性,它只能访问Foo
上的属性,这正是我所期望的。
另请注意,我们可以将类型Foo
的值分配给T
,但只能通过传入Foo
作为参数,而不是使用let a: T = new Foo()
}
上面的代码是我更大的应用程序的一个非常小的简化测试用例。我想这样做:
class Foo {
// Various properties and methods
protected _foo: number;
}
class Bar extends Foo {
// Various properties and methods
protected _bar: number;
}
class Qux<T extends Foo> {
// Various properties and methods which work on Array<T>
protected _list: Array<T>;
get list(): Array<T> {
// Do initialization / caching / etc.
return this._list;
}
}
class Corge<T extends Bar> extends Qux<T> {
constructor() {
super();
this._list = [new Bar()];
let value: Array<Bar> = this.list;
}
}
这允许我将通用方法放入Qux
Array<Foo>
,这些方法也适用于Corge
,即使Corge
使用Array<Bar>
}
但由于类型错误,这不起作用。
答案 0 :(得分:2)
T
扩展Foo
,这意味着类型T
的值可分配给Foo
类型的变量。不是相反。
使用更具体的例子,假设你有:
class FooPlus extends Foo {
public fooPlusMethod() { }
}
function test<T extends Foo>() {
let x: T = new Foo();
}
test<FooPlus>();
在这种情况下,函数中的变量x
应该具有类型FooPlus
,因此您应该能够调用x.fooPlusMethod()
,但是您要为其分配一个新实例是Foo
的,没有那种方法。
以下是基于您自己的代码的相同示例:
let x = new Corge<BarPlus>();
现在,当我调用x.list
时,我希望它返回Array<BarPlus>
,因为它扩展了Qux<BarPlus>
实现了该方法,但我将返回一个包含一个数组的数组Bar
类型的元素,它没有实现我期望从BarPlus
获得的所有功能。
答案 1 :(得分:0)
T
可能会有其他成员,因此您可以将类型T
的值分配给Foo
类型的变量,但不能相反。
这里的例子:
type Foo = { a: number };
type Bar = { a: number, b: string };
let foo: Foo = { a: 1 };
let bar: Bar = { a: 1, b: '1' };
foo = bar; // OK
bar = foo; // error: "Property 'b' is missing in type 'Foo'"
也许是一个更简单的例子:
class Shape {
type: string
}
class Square extends Shape {
width: number;
}
let shape: Shape = new Square(); //OK
let square: Square = new Shape(); //error - that's what you're trying to do