JavaScript Type Checking with Flow — Interfaces

John Au-Yeung
Feb 10 · 4 min read
Photo by David Švihovec on Unsplash

Flow is a type checker made by Facebook for checking JavaScript data types. It has many built-in data types we can use to annotate the types of variables and function parameters.

In this article, we’ll look at how to create interfaces to create multiple types that are compatible with each other by defining a common structure for multiple types.

Why We Need Interfaces?

We need interfaces because types in Flow are nominally typed. This means that they’re identified by name, so we can’t replace one type with another even if they have the same structure.

For example, if we have:

class A {
foo() { return 'a'; }
}
class B {
foo() { return 'b'; }
}
const foo: A = new B();

We’ll get an error because A and B aren’t considered to be compatible even though they have the same structure.

Interfaces can solve this since 2 types that implement the same interface will be considered the same:

interface Foo {
foo(): string;
}
class A implements Foo{
foo() { return 'a'; }
}
class B implements Foo{
foo() { return 'b'; }
}
const foo: Foo = new A();
const bar: Foo = new B();

In the code, we set the type of our variable or constant to be the interface, and then we can set it to anything of types that implement the interface.

To implement an interface, we use the implements keyword. This enforces the structure of the classes the implement the interface.

We can also implement multiple interfaces in one class. For example, we can write:

interface Foo {
foo(): string;
}
interface Bar {
bar(): number;
}
class A implements Foo, Bar{
foo() { return 'a'; }
bar() { return 1; }
}

Then the A class needs to have everything in both Foo and Bar interfaces.

Interface Syntax

As we can see above, we define an interface with the intreface keyword. For example, we write:

interface Foo {}

We can add methods to it by writing:

interface Foo {
fooMethod(value: string): number;
}

Then whatever implements Foo have to implement fooMethod , which has to take a string and return a number.

We can add properties as follows:

interface Foo {
prop: number;
}

Also, we can make it optional by writing:

interface Foo {
prop?: number;
}

Interfaces can also be made dynamic with indexer properties, which we can define as follows:

interface Foo {
[prop: string]: number;
}

Interface Generics

We can also add Generic type parameters to interfaces. For example, we can write:

interface Foo<A, B, C> {
foo: A;
bar(val: B): C;
}

Then when we want to use the interface, we can add real types in place of the generic type markers as follows:

interface Foo<A, B, C> {
foo: A;
bar(val: B): C;
}
let foo: Foo<number, boolean, string> = {
foo: 1,
bar(val: boolean){
return '';
}
};
Photo by Christian Wiediger on Unsplash

Making Interface Properties Read and Write Only

We can make a property in an interface read-only by adding a + sign in front of it. For example, we can write:

interface Foo {
+foo: number;
-bar: number;
}

To make foo read-only and bar write-only.

Read-only properties can’t be reassigned, so given the Foo interface that we defined above, if we write:

let obj: Foo = {
foo: 1,
bar: 2
}
obj.foo = 2;

We’ll get an error.

Write-only properties can only be written to, so we can assign a value to it:

let obj: Foo = {
foo: 1,
bar: 2
}
obj.bar = 2;

But we’ll get an error if we write:

let y = obj.bar;

Since we can only write to it but not read its value.

In Flow, interfaces allow us to define contracts to let other classes implement the interface. Anything instances of classes that implement a given interface are considered to have compatible types.

With interfaces, we can also set properties as writable and readable. Also, we can add generic type markers so that we can reuse interfaces with different types.

Also, we can add dynamic properties to interfaces with index properties.

John Au-Yeung

Written by

Web developer. Subscribe to my email list now at http://jauyeung.net/subscribe/ . Follow me on Twitter at https://twitter.com/AuMayeung

JavaScript in Plain English

Learn the web's most important programming language.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade