有人可以解释一下,为什么这段代码不起作用:
class Fooable {
foo: string;
}
class Barable extends Fooable {
bar: boolean;
}
function simplifiedExample<T extends Fooable>(): Array<T> {
let list = new Array<T>();
list.push(new Barable());
return list;
}
Barable正在扩展Fooable。当T必须是Fooable时,为什么我不能将Barable添加到数组? 这里的代码在playground
修改
问题是,simplifiedExample()是基类的重写,基类只是一个定义。因为是一个混合的项目JS / TS。
请参阅: new playground
我找到了一个带有演员的解决方案,但它似乎不适合我:
class BarableService extends FooableService {
simplifiedExample<T extends Fooable>(): Array<T> {
let list = new Array<Fooable>();
list.push(new Barable());
return list as Array<T>;
}
}
答案 0 :(得分:1)
虽然T
类型与Fooable
兼容且类型Barable
与Fooable
兼容,但这并不意味着Barable
与T
兼容{1}}。
例如:
class Bazable extends Fooable {
baz: number;
}
const result: Bazable[] = simplifiedExample<Bazable>();
这让我想起了一点哲学,因为你可以看到这是一个不合理的问题:
If T (Bazable) is a Fooable
And Barable is a Fooable
Then T (Bazable) is a Barable
或者...
If T (Lion) is a Cat
And Tiger is a cat
Then T (Lion) is a Tiger
Cat
/ \
/ \
Lion != Tiger
由于结构类型系统,TypeScript中有许多情况可以在没有泛型的情况下解决。您可能会发现对您Barable
的诚实态度会很好:
function simplifiedExample(): Barable[] {
let list: Barable[] = [];
list.push(new Barable());
return list;
}
除了兼容的结构之外,您不需要任何其他内容来传递类型检查:
class Bazable {
foo: string;
bar: boolean;
}
const a: Bazable[] = simplifiedExample();
甚至:
class Bazable {
bar: boolean;
}
const a: Bazable[] = simplifiedExample();
当然:
const a: Fooable[] = simplifiedExample();
如果这不符合您的要求,您可能需要提供一个您认为需要引入通用类型的示例。通常情况下,如果你想在函数中构造一个新的T
,而不是一个固定的类型。
答案 1 :(得分:0)
数组列表的类型是已知的,它应该是Fooable
,因此返回类型。
答案 2 :(得分:0)
正如@Fenton指出的那样,T
和Barable
的兼容性无法在函数中检查。如果您需要创建T
的新实例,则可以传入构造函数:
function simplifiedExample<T extends Fooable>(ctor: new ()=> T): Array<T> {
let list = new Array<T>();
list.push(new ctor());
return list;
}
const result1: Bazable[] = simplifiedExample(Bazable);
const result2: Barable[] = simplifiedExample(Barable);