Type is the ultimate. Type eclipses everything.
The day has come. You staring at the screen. In front of you an interface
and a type
. You’re wondering. They seem to do the same thing. Is it possible?! Are them really doing the same thing TypeScript?
What’s the difference? Why should I use one instead of the other? Did I use them wrong all along? All fair questions…
Once upon a time…
Back in the day, when OOP was cool, interfaces
were meant to group methods so that classes
could implement them.
And this was nice as it imposed a constraint on classes
.
If the class
did implement an interface
you knew the interface
methods
were there.
interface is a group of related methods with empty bodies
— The Java™ Tutorials
At the same time in other languages, there were data structures that were meant for organising, managing and storing data.
And this was nice too because with data structures
you focus just on data
, no stress on business logic
.
It may seem a subtle distinction but it’s quite important.
Having a clear separation data
vs business logic
means you have a clear understanding of the information you want to manage vs the algorithms that actually do the work for you.
Now, there is a particular data structure
called object
.
objects
are a little bit funny as they can be data
only — as such, they behave as pure data structures
— or they can have business logic
. In that case, you mess with methods
like sendConfirmationEmail
or createUserAccount
kind of thing.
Note: the mere fact you have a method
doesn’t mean you’re dealing with business logic
though.
For example, there are data structure
in JavaScript like Array
which are data structure
but at the same time have methods
like push
, pop
, filter
and map
.
Welcome TypeScript
When TypeScript first appeared in 2012 it had to deal mainly with objects
.
This is because JavaScript didn’t have classes
back then.
In fact, JavaScript introduced classes
only in 2015 with ES6
.
But TypeScript, despite being a JavaScript superset, included several ES6
proposed features and shipped with classes
.
And so, with support for objects
and classes
, TypeScript extended
the scope of interface
to model objects
as well.
For unusual that it is from an OOP perspective, in this context, it made plenty of sense having interfaces
to spec methods
and properties
.
Interfaces provide the ability to give names to object types and the ability to compose existing named object types into new ones.
— TypeScript Language Specification - Interface : 2013
No object, no interface
But what happens when you want to rename a number
into something more meaningful, let’s say a PhoneNumber
? In that case, you’re not dealing with an object
, you can’t use an interface
there.
And so, in 2015 with TypeScrpit 1.4, type aliases
were introduced.
Because of type aliases
, you can have renamed primitives
which are types
like type Coordinate = number
or type PhoneNumber = number
and union types
which are types
like type ButtonType = 'submit' | 'reset' | 'button'
.
Unlike an interface declaration, which always introduces a named object type, a type alias declaration can introduce a name for any kind of type, including primitive types and union types.
— TypeScript Language Specification - Type Aliases : 2015
// CASE : INTERFACE AND TYPE
// interfaces and types are interchangeable
// declare the shapes of objects
interface Point {
x: number;
y: number;
}
type Point = {
x: number;
y: number;
}
// function types
// note: this is possible because functions are
// objects in javascript
interface GreetFunction {
(a: string) => void;
}
type GreetFunction = (a: string) => void;
// CASE : TYPE ONLY
// you can't do this with interfaces
// renamed primitives
type Coordinate = number;
// union types
type StringNumber = string | number;
// variadic tuple types
// Introduced in Typescript 4
type Strings = [string, string];
type Numbers = [number, number];
type StrStrNumNumBool = [...Strings, ...Numbers, boolean];
We’re the same but not quite
A part of rename primitives
and union types
, are interfaces
and types
the same?
Well, kind of.
If you read the docs Differences Between Type Aliases and Interfaces, you’ll find listed a cryptic difference named multiple merged declarations
.
multiple merged declarations
means that interfaces
support overloading
but types
don’t. So, you can keep extending an interface
but you can’t with type
.
// Probably the other big unusual difference is multiple merged declarations
// declaration := when we use the interface or type keyword
// multiple := more than one declaration
// merged := the declarations get combined
// declaration 1
interface Point {
x: number;
}
// declaration 2
interface Point {
y: number;
}
// The two declarations get merged
// now Point is {x, y}
// with type it would give an error
type Point = {
x: number;
}
type Point = {
y: number;
}
// Error Duplicate identifier 'Point'.(2300)
Which one should I use then?
Warning, opinions ahead.
The official docs recommend using interfaces
when possible and types
only if in need.
However, I wonder if we wouldn’t be better off having types
for data structures
and interfaces
for business logic
(methods
and classes
).
In this way, the use of interfaces
would fit back to the original OOP meaning, leaving type
as synonym for data
.
This would hide the prototype
side of JavaScript even more I guess and probably would push people even further towards classes
but it would be for the best in the long run.
Summary up
We looked at the historical context of interface
and data structure
.
Then we saw the evolution of interface
and type
in TypeScript.
Next, we listed the main interface-type
differences which are renaming primitives
, union types
and multiple merged declarations
.
After that, I speculate about the use of interface
vs type
, in particular interface
for business logic
and type
for data structure
.
With all this mental frame, you should have enough context to pick the best approach for your project.
If you want to dig further, I would recommend reading TypeScript Language Specification: 2013 Chapter 7 Interfaces, TypeScript Language Specification: 2015 Section 3.9 Type Aliases to see the evolution interface-type
and lastly, Douglas Crockford Classical Inheritance in JavaScript if you’re into the prototype
side of the force.
Links
- Interfaces vs Types in TypeScript
- Why does TypeScript programmers prefer interface over type
- Differences Between Type Aliases and Interfaces
- More on Functions
- The Java™ Tutorials: What Is an Interface?
- Interface (object-oriented programming)
- Object: MDN
- Prototype-based programming
- TypeScript Language Specification: 2013
- TypeScript Language Specification: 2015