类型' Barable'的论点不能分配给' T'类型的参数。

时间:2017-11-24 11:53:24

标签: typescript generics inheritance

有人可以解释一下,为什么这段代码不起作用:

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>;
    }
}

3 个答案:

答案 0 :(得分:1)

虽然T类型与Fooable兼容且类型BarableFooable兼容,但这并不意味着BarableT兼容{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

Generic vs Structural

由于结构类型系统,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指出的那样,TBarable的兼容性无法在函数中检查。如果您需要创建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);