TypeScript 工厂模式说 属性 不存在

TypeScript factory pattern says property doesnt exist

我试图在 TypeScript 中实现工厂模式,但我无法访问超级 class 中不存在的子函数。 (它有效,但编译器给我一个错误)。

结构:

abstract class Animal {
    walk(meters:number) { ... }
}

class Elephant extends Animal {
    walk(meters:number) { ... }
}

class Eagle extends Animal {
    walk(meters:number) { ... }
    fly(meters:number) { ... }
}

我的工厂:

class Zoo {
    animals:Animal[] = [];

    addAnimal(type:string): Animal {
        var a: Animal;

        switch(type) {
            case 'elephant':
                a = new Elephant();
                break;
            case 'eagle':
                a = new Eagle();
                break;
            default:
                throw new Error('Animal of type \'' + type + '\' doesn\t exist');
        }

        this.animals.push(a);
        return a;
    }
}

然后:

var sammy:Animal = addAnimal('eagle');
sammy.fly(15);

这给了我: 错误:TS2339:属性 'fly' 在类型 'Animal' 上不存在。

我也尝试投射:

var sammy:Eagle = addAnimal('eagle');
sammy.fly(15)

这给了我: 错误:TS2322:类型 'Animal' 不可分配给类型 'Eagle'。 属性 'fly' 在类型 'Animal' 中缺失。

我在 TypeScript 页面上做了一个代码游乐场:http://bit.ly/21yXXjf

快速修复

您可以使用类型断言将类型检查从 TypeScript 转移到您自己手中。

var sammy = <Eagle><any>zoo.addAnimal('eagle');
sammy.fly(15)

这可能会导致问题,因此有更好的解决方案来解决您的问题(以及一般的工厂问题)...

更好的解决方案

使用专门的签名 return 基于静态字符串的正确类型:

class Zoo {
    animals:Animal[] = [];

    addAnimal(type: 'elephant'): Elephant;
    addAnimal(type: 'eagle'): Eagle;
    addAnimal(type: string): Animal;
    addAnimal(type: string): Animal {
        var a: Animal;

        switch(type) {
            case 'elephant':
                a = new Elephant();
                break;
            case 'eagle':
                a = new Eagle();
                break;
            default:
                throw new Error('Animal of type \'' + type + '\' doesn\t exist');
        }

        this.animals.push(a);
        return a;
    }
}

var zoo = new Zoo();

// No type assertion needed, sammy is an eagle!
var sammy = zoo.addAnimal('eagle');
sammy.fly(15)

您正在返回类型为 Animal 的动物,然后尝试访问 属性 'fly',此类型不存在,可能的解决方案是添加 属性 'fly' 到 Animal class,或从 addAnimal 方法 addAnimal(type:string): Animal {} 中删除 Animal 类型,或者您可以将代码更改为:

var sammy = <Eagle>myZoo.addAnimal('eagle'); // This woudl work without errors!

只需将 <Eagle> 类型添加到您的方法调用