Reputation: 8913
Im trying to implement the factory pattern in TypeScript, but i can't access the child-functions that doesnt exist in the super class. (It works, but the compiler is giving me an error).
Structure:
abstract class Animal {
walk(meters:number) { ... }
}
class Elephant extends Animal {
walk(meters:number) { ... }
}
class Eagle extends Animal {
walk(meters:number) { ... }
fly(meters:number) { ... }
}
My factory:
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;
}
}
Then:
var sammy:Animal = addAnimal('eagle');
sammy.fly(15);
This gives me: Error: TS2339: Property 'fly' does not exist on type 'Animal'.
Also i tried to cast:
var sammy:Eagle = addAnimal('eagle');
sammy.fly(15)
Which gives me: Error: TS2322: Type 'Animal' is not assignable to type 'Eagle'. Property 'fly' is missing in type 'Animal'.
I made a code playground on TypeScript page: http://bit.ly/21yXXjf
Upvotes: 0
Views: 458
Reputation: 248
You are returning an animal with type Animal and then trying to access property 'fly', which does not exists in this type, possible solution is to add property 'fly' to Animal class, or remove Animal type from addAnimal method addAnimal(type:string): Animal {}
, or you could change your code to this:
var sammy = <Eagle>myZoo.addAnimal('eagle'); // This woudl work without errors!
Just add <Eagle>
type to your method call
Upvotes: 0
Reputation: 250882
You can use type assertions to take the type checking away from TypeScript and into your own hands.
var sammy = <Eagle><any>zoo.addAnimal('eagle');
sammy.fly(15)
This can result in problems, so there is a better solution to your problem (and the factory problem in general)...
Use specialized signatures to return the correct type based on the static string:
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)
Upvotes: 2