Typescript 泛型扩展类时出现类型错误
此类型脚本代码:Typescript 泛型扩展类时出现类型错误,typescript,Typescript,此类型脚本代码: class Foo {} function bar<T extends Foo>(): void { let value: T = new Foo(); } 这在我看来是错误的:T扩展自Foo,因此Foo应该与T兼容 为什么会发生这种错误 为了证明使用T extends Foo在某些情况下可以正确工作,下面是另一个没有给出类型错误的示例: class Foo { protected _foo: number; getFoo(): number {
class Foo {}
function bar<T extends Foo>(): void {
let value: T = new Foo();
}
这在我看来是错误的: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());
这允许我将通用方法放入Qux
中,该方法适用于Array
,这些方法也适用于Corge
,即使Corge
使用Array
但由于类型错误,这不起作用。
t
扩展了Foo
,这意味着t
类型的值可分配给Foo
类型的变量。而不是相反
要使用更具体的示例,请假设您有:
class FooPlus extends Foo {
public fooPlusMethod() { }
}
function test<T extends Foo>() {
let x: T = new Foo();
}
test<FooPlus>();
现在,当我调用
x.list
时,我希望它返回一个数组
,因为它扩展了实现该方法的Qux
,但我将返回一个数组,该数组将包含Bar
类型的元素,它没有实现我期望从BarPlus
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
不,我不希望能够调用
x.fooPlusMethod()
,因为签名说T
必须从Foo
扩展,所以在函数中我们只知道T
与Foo
具有相同的方法(可能还有一些其他未知方法)。抱歉,响应有点晚。类/方法的签名是泛型的,但一旦您将其指定为某种类型,您就告诉它一个特定的T
。在这里,调用test()
表示我正在调用方法test
,其中T
是FooPlus
;不仅仅是扩展Foo
的任何T
。因此,对于该调用,在测试中,T
被FooPlus
替换。如果还不清楚,请告诉我。看看第二个示例,我使用您自己的类型Corge
来解释x
具有类型Corge
,因此x.list
将具有类型数组
(不是Array
,因为此时已经指定了T)。但是您的代码将返回一个数组
,该数组不可分配给数组
。是的,但这不是问题:如果一个方法接受类型为t extensed Foo
的参数,那么它应该只允许使用Foo
的成员,因为在这个方法中,我们所知道的关于T
的唯一事情是它有Foo
的成员,我们对T
一无所知。此外,在您的回答中,您证明了可以将条分配给Foo
,但我的问题是,在我的示例中,我想将条形图
分配给Foo
,但由于类型错误,我无法分配。这就是问题所在-我已经向您解释了为什么不能将新Foo
分配给t
。在我的示例中,Bar
与您的示例中的T
相似您的新示例仍然是错误的,它与您的原始示例完全相同。我确实理解子类型,我的示例应该能够正确工作。我用一些进一步的信息更新了我原来的问题,证明了为什么我的代码应该工作。如果您试图将基类型的值赋给子类型的变量,它如何工作<代码>列表
属于数组
类型,其中T扩展了Bar
意思是T
是Bar
的子类型。因此,回到形状示例,您正在尝试:let list:Array=[new Shape()]
let x = new Corge<BarPlus>();
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