从继承自基类型 - Typescript 的类列表中返回类型 T 的项



我有一个类(Foo(,用于保存项目列表,其所有项目列表都继承自基类型(IBar(,此列表可以包含任意数量的这些项目。

我遇到的问题是我正在尝试在 Foo 上创建一个 get 方法,该方法采用仅限于从 IBar 继承的类型类型的泛型类型。

我目前拥有的接口和类是:

interface IBar {
bar : string;
}
interface IFizz extends IBar {
buzz : string;
}
class Foo {
get<T extends IBar>() : T {
var item = this.list[0];
return item;
}
list : Array<IBar>;
}

我尝试运行的代码是:

var foo = new Foo();
var item = foo.get<IFizz>();

我知道在上面列表是空的,但这更多的是试图让 Typescript 编译器不显示错误。调用 foo.get 的行很好并且没有错误,问题是 get 方法本身。 我从上面得到的错误是"类型'IBar'不能分配给类型'T'"。

如果查看 C# 作为参考,上述内容将起作用(我相信(,并且欢迎任何书面示例来帮助我解决这个问题。

谢谢

上面的代码在 C# 中也不起作用。这两种语言都试图阻止您执行此操作,因为这不是类型安全的。请考虑以下代码:

class Foo {
get<T extends IBar>() : T {
var item = this.list[0];
return item;
}
list : Array<IBar> = [ new OneClass() ];
}
var foo = new Foo();
var item = foo.get<AnotherClass>();

OneClassAnotherClass都实现了IBar,但list[0]属于OneClass类型,但调用方请求AnotherClass的实例。因此,如果编译器允许你编写的代码,你会item键入AnotherClass但持有可能导致运行时错误的OneClass实例。

就像在 C# 中一样,您可以强制打字稿编译器允许您使用类型断言(或类似的 C# 强制转换(执行此操作。尽管您可以执行此操作,但您应该有另一种机制来确保数组中的项目实际上具有正确的T类型:

class Foo {
get<T extends IBar>() : T {
var item = this.list[0];
return item as T;
}
list : Array<IBar> = [];
}
var foo = new Foo();
var item = foo.get<IFizz>();

你试图断言索引 0 处的项目是一个IFizz,而不仅仅是一个IBar;这不能静态地保证给定Foo的声明,它只能在运行时使用特定数据为真。虽然你可以断言它(return item as T;(,但这只是隐藏了问题:当代码实际运行时,索引 0 处的项目可能不是IFizz

如果列表要包含IFizz,则应声明这样做。如果它要包含任何类型的IBar,则应声明这样做,并且将其用于IFizz实例的任何代码都负责确保这是真的。

相反,Foo应使用实际IBar类型对其进行参数化:

class Foo<T extends IBar> {
get() : T {
var item = this.list[0];
return item;
}
list : Array<T>;
}

然后

var item = foo.get();

最新更新