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
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)