Add types to your classes

INPUT · Slides

Implement an interface

01 / 05

Declare "I meet this shape"

The interface you wrote in chapter 2 put a name on a shape. Write implements after a class name and it becomes a declaration that "this class meets that shape".

Inside an interface, a method is written as just a name and a shape, like speak(): string;. No body. Writing the body is the class's job.

After that you declare class Dog implements Animal and put everything you promised into the class.

interface Animal {  speak(): string;}class Dog implements Animal {  speak(): string {    return "woof";  }}console.log(new Dog().speak());

Result

woof

02 / 05

You can promise fields too

An interface is not only for methods. You can line up the fields you want it to hold as well.

The class declares them and fills them in the constructor. That part is exactly as in the lessons so far.

interface Animal {  name: string;  speak(): string;}class Cat implements Animal {  name: string;  constructor(name: string) {    this.name = name;  }  speak(): string {    return this.name + " says meow";  }}console.log(new Cat("Tama").speak());

Result

Tama says meow

03 / 05

Forget one and the class is stopped

Declare implements Animal while forgetting to write speak and you get an error where you wrote the class.

"Class 'Dog' incorrectly implements interface 'Animal'." "Property 'speak' is missing in type 'Dog' but required in type 'Animal'." That gets rid of the accident where you meant to write it later and it shipped without you.

interface Animal {  name: string;  speak(): string;}class Dog implements Animal {  name: string;  constructor(name: string) {    this.name = name;  }}

Result

Type error: Class 'Dog' incorrectly implements interface 'Animal'.
  Property 'speak' is missing in type 'Dog' but required in type 'Animal'.

04 / 05

Classes with the same promise can line up

Any number of classes may implement the same interface. The promise is the same, so they go into one array and are treated the same way.

Write the array type as Animal[] and calling speak() is guaranteed, whether the contents are a Dog or a Cat.

interface Animal {  speak(): string;}class Dog implements Animal {  speak(): string {    return "woof";  }}class Cat implements Animal {  speak(): string {    return "meow";  }}const list: Animal[] = [new Dog(), new Cat()];for (const d of list) {  console.log(d.speak());}

Result

woof
meow

05 / 05

How it differs from extends

They look alike but their jobs differ.

  • extendsyou get the parent's insides (it works without writing them)
  • implementsyou only promise a shape (you write the insides yourself)

implements hands you nothing. In exchange, you always find out when you forget something. Use extends when there are shared insides, implements when you only want the shapes to line up. Right, have a go.