Trying out polymorphism in TypeScript I found out about kind of a weird behaviour. At least I consider this a weird behaviour with myself coming from Java, where rules tend to have a much stricter tendency than in TypeScript.
So, I created a little example that showcases TypeScript only respecting the structure, but not the logical thought behind implementing and using interfaces in classes.
interface Bird {
tweet(): string;
}
class Crow implements Bird {
constructor(private message: string) { }
tweet(): string {
return this.message + "<br />";
}
}
class Sparrow implements Bird {
constructor(private message: string) { }
tweet(): string {
return this.message + "<br />";
}
}
class ManWithAHat {
constructor(private message: string) { }
tweet(): string {
return this.message + "<br />";
}
}
class Chitter {
static do(bird: Bird): string {
return bird.tweet();
}
}
// Getter for num returned 4
let element = document.getElementById('content');
let output: string = "";
const crow = new Crow("Crow says something!");
output += Chitter.do(crow);
const sparrow = new Sparrow("Sparrow says something!");
output += Chitter.do(sparrow);
const manWithAHat = new ManWithAHat("A man with a hat shouldn't be able to talk!");
output += Chitter.do(manWithAHat);
element.innerHTML = output;
The classes Crow
and Sparrow
both implement the interface Bird
, forcing them to implement the tweet(): string
method. The class ManWithAHad
does not implement the Bird
interface, but by coincidence has the same method tweet(): string
. The static method do(bird: Bird): string
in the class Chitter
only accepts Bird
as value. Then all three classes are instantiated and passed over to Chitter.do(bird: Bird): string
.
Now, there is no error. All three classes are accepted by Chitter.do(bird: Bird): string
, even the ManWithAHat
class.
My question is, whether there is any case, where it acutally makes sense for Chitter.do(bird: Bird): string
to also accept ManWithAHat
as parameter? My second question, based on this, is whether there is a way in TypeScript to force Chitter.do(bird: Bird): string
to decline any parameter not implementing the Bird
interface, regardless whether the structure is the same or not.