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