Reputation: 1
Below is the syntax, using TypeScript,
interface Animal{
eat():void;
sleep():void;
}
class Mammal implements Animal{
constructor(private name:string){
console.log(this.name, "is alive");
}
eat(){
console.log("Like a mammal");
}
sleep(){
console.log("Like a mammal");
}
}
class Dog extends Mammal{
eat(){
console.log("Like a dog")
}
}
let m: Mammal = new Dog("Prisca"); // looks fine
let d: Dog = new Mammal("abomination"); // This also works
For variable d
, TypeScript supports Structural typing and type Dog
has atleast properties(similar) that Mammal
has, after overriding. So variable d
can still point to Mammal
type object until one more property is added in Dog
type.
In TypeScript, How to avoid such pitfalls?
Upvotes: 1
Views: 537
Reputation: 18312
There's no way to avoid it. Structural typing is a need in TypeScript for interoperability with JavaScript and JSON. Is a little price we've got to pay, and a consquence of TypeScript purpose, which is to add types to JavaScript while still being completely compatible with it and, especially, with existent codebase.
The only way to avoid it, in your example, would be to add something to Dog
that Mammal
does not have, or, maybe, to make Mammal
an abstract class, so it can't be directly instantiated. In this case it would be logical, as you might create a new Dog
, Cat
, Horse
... but not just a new Mammal
.
As pointed by Titian and Estus, an easy option if you don't want to make Mammal
abstract and want to go the way of differentiating the classes even if you don't really want to add anything extra, would be to add an irrelevant private property without (almost) any effect at runtime:
private isDog: undefined;
Upvotes: 3