Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript interfaces and implementation

Tags:

typescript

I was having a play around with TypeScript and interfaces. I have the following piece of code

interface Control {
    name: string;
    onSelect():string;
}

class Button {
    name:string="button";
    onSelect = function() {
        return "hello";
    }
}

var a:Button = new Button();
var b:Control = {"name": "arbitrary", "onSelect": () => { return "ahoy!"; }};

var trigger = function(c:Button) {
    console.log(c.name, "says", c.onSelect());
}

trigger(a);
trigger(b);

Which compiles and runs without complaining. Can anyone please explain why my trigger function accepts b even though it expects to get a type Button and b is of type Control.

Even if Button were to explicitly implement Control, I'm asking for a Button not a Control. For all intended purposes, Button may contain additional members.

Is TypeScript inferring the implementation just because they are structurally the same? Are you allowed to pass an interface where an implementing class is expected? (shouldn't it be the other way around?)

like image 391
Andrei Nemes Avatar asked Sep 20 '25 01:09

Andrei Nemes


1 Answers

As described in this TypeScript doc:

One of TypeScript’s core principles is that type checking focuses on the shape that values have. This is sometimes called “duck typing” or “structural typing”.

In "duck typing":

If it looks like a duck and swims like a duck, then in it's likely a duck.

In other words, TypeScript examines the shape (methods and properties) of a supplied object or type. If the supplied object contains all the properties and methods described by an interface, then the object can, in all likelihood, be treated as an object that is compatible with the described interface.

In your example, your interface and class look exactly the same, so TypeScript treats your object as compatible with the described interface.

If you examine the generated JavaScript, note that there is no mention of your interface at all - this is because TypeScript Interfaces are essentially developer-supplied type metadata that help TypeScript validate type compatibility.

like image 144
Rich Turner Avatar answered Sep 23 '25 06:09

Rich Turner