Interfaces in TypeScript

Interfaces provide a very powerful way of to define entities that most conform a definition – in other words we can specify that an entity Person must have a name and an age property, and since we are in TypeScript we can also specify that name must be a string and age must be a number.

TypeScript’s type-checking focuses on the shape that values have – this is referred to as duck typing. Think of it this way – if we did not have duck typing and we’d like to use a function on an object the system must make sure that the function exists. For example, consider a Car object where we’d like to call the startEngine method. Passing the Car object to a function and calling its method means that we need to make sure that we only accept the Car object type. With duck typing we can specify that our function accepts any object and as long as it has a startEngine method, the code will work.

Interfaces are a way to making sure that objects that we create conform certain rules.

Let’s go ahead and actually create an interface:

interface IWarrior {
  name: string;
  health: number;
}

We have defined an interface above called IWarrior and specified that all objects that will implement this interface should contain a name and a health property. Let’s put our interface to use:

let myWarrior: IWarrior = {
  name: 'John the Nomad',
  health: 100
};

Using Visual Studio Code as our editor helps us to identify potential errors with our code immediately. We can see that upon creating a variable, assigning it the IWarrior interface and specifying properties to it other than what we have added in the interface will immediately display errors.

let myWarrior: IWarrior = {
  name: 'John the Nomad',
  health: 100,
  weapon: 'sword' // Object literal may only specify known properties, and 'weapon' does not exist in type 'IWarrior'.
};

There’s of course a way to define optional properties as well and in order to achieve this all we need to do is add a question mark after the property name:

interface IWarrior {
  name: string;
  health: number;
  weapon?: string;
}

let myWarrior: IWarrior = {
  name: 'John the Nomad',
  health: 100,
  weapon: 'sword' // this property is now optional
};

I already hear what you’re thinking – can a property be made read only by specifying some magic in the interface itself. The answer is yes, TypeScript allows us to specify read only properties for interfaces:

interface IWarrior {
  name: string;
  readonly health: number;
  weapon?: string;
}

let myWarrior: IWarrior = {
  name: 'John the Nomad',
  health: 100,
  weapon: 'sword'
};

myWarrior.health = 80; //Cannot assign to 'health' because it is a constant or a read-only property.

Interfaces are very useful when it comes to declaring entities and their properties and allow developers to enforce these values in other parts of the codebase.