Types
Transpile-Time Type Checking
Warning
typings
tool to install third-party type definitions. This has been deprecated since TypeScript
version 2.0 in favour of the @types
npm packages, see the end of this lecture for information on using @types
.
Some of the most common mistakes we make while writing JavaScript code is to misspell a property or a method name.
We only find out about the mistake when we get a runtime error, that is to say when we are running our application.
Note
Other languages like C++ or Java have something called type checking, during a compilation phase it first checks for some simple mistakes in the code and raises an error if it finds any.
TypeScripts transpilation mechanism also performs type checking, however it only works when we tell TypeScript the type of things.
e.g. in JavaScript we might write:
Copylet a;
a = 1;
a = '2';
We expected the type of the a
variable to remain a number over its life. But by mistake we assigned a string '2'
to a
, this doesn’t cause an error in JavaScript.
Only if one of the functions which depends on a
starts misbehaving do we even get a clue that something might be wrong.
However with TypeScript we can clearly state that we want the a
variable to always hold a number, like so:
Copylet a: number = 1;
Then if somewhere else in our code we wrote:
Copya = "1";
We get this error:
Copyerror TS2322: Type 'string' is not assignable to type 'number'.
If we take advantage of types in TypeScript the transpiler will warn us with a transpile-time errors.
Supported Types
Basic Types
We can support boolean, number and string.
Copylet decimal: number = 6;
let done: boolean = false;
let color: string = "blue";
Arrays
We have two ways of describing the types of arrays.
The first is to use the brackets notation []
, like so:
Copylet list: number[] = [1, 2, 3];
The above indicates to TypeScript that this array should only hold numbers.
The second way uses a generic type specifically Array<Type>
, like so:
Copylet list: Array<number> = [1, 2, 3];
Note
Functions
We can describe a variable as one that will only point to a function, like so:
Copylet fun: Function = () => console.log("Hello");
With TypeScript we can also define the expected return type of a function, like so:
Copyfunction returnNumber(): number {
return 1;
}
The above lets TypeScript know that the function should only return a number.
Enum
An Enum is a datatype consisting of a set of named values. The names are usually identifiers that behave as constants. Enums were introduced in ES6.
Copyenum Direction {
Up,
Down,
Left,
Right
}
let go: Direction;
go = Direction.Up;
Class & Interface
Classes and Interfaces, whether created by you or others, are also types of things. So we can use them where we would use any of the
Copyclass Person {};
let person: Person;
let people: Person[];
Any
If we don’t know the type of something we can fall back to using any
.
If used it doesn’t provide any type checking but does make it clear that we intentionally don’t know the type, rather than we forgot to add the type.
Copylet notsure: any = 1;
notsure = "hello"; // This is fine since we don't do type checking with any
Void
void
means no type, it’s typically used to indicate that a function will not return anything at all, like so:
Copyfunction returnNothing(): void {
console.log("Moo");
}
Type Assertion
Sometimes we end up in a situation where we know more than TypeScript about the type of something. In those situations we can use type assertions as a hint to the transpiler about the type of something, like so:
Copylet value: any = "Asim Hussain";
let length: number = (<string>value).length;
(<string>value)
lets TypeScript know that we believe the type of value to be string.
Generics
How can we create
Take for instance this example:
Copyclass Audio {}
class Video {}
class Link {}
class Text {}
class Post {
content: any;
}
We have a class called Post which has a content
property. The content might be an instance of Audio, Video, Link or Text classes.
We could ignore the type of content and just use any
like the example above but this doesn’t give us the benefit of type checking.
We can create seperate AudioPost
, VideoPost
, LinkPost
and TextPost
types, like so:
Copyclass AudioPost {
content: Audio;
}
class VideoPost {
content: Video;
}
class LinkPost {
content: Link;
}
class TextPost {
content: Text;
}
But apart from being verbose and time-consuming it assumes we know all the content types upfront. Maybe a consumer later on would like to create a VRPost
type.
With generics we can dynamically generate a new type by passing into the Post type a type variable, like so:
Copyclass Audio {}
class Video {}
class Link {}
class Text {}
class Post<T> {
content: any;
}
<T>
above is the generic syntax and T
is the type variable. We could name it anything but the convention if there is only one is to call it just T
.
Then we can use T
wherever we would use a type, like so:
Copyclass Post<T> {
content: T;
}
Finally, when we want to create a specific type of Post we can declare it like so:
Copylet videoPost: Post<Video>;
Optional Types
By default we don’t have to add types when using TypeScript, we could just leave them out.
Copylet answer;
answer = 42;
TypeScript won’t perform any type checking for the above and assumes a type of any
.
Important
This behaviour is controlled by the noImplicitAny
flag in tsconfig.json
. If set to false
then TypeScript assumes any
for missing types, of set to true
then TypeScript throws an error if no type is present.
Opinion is split as to whether to keep this to true
or false
, by default it’s set to false
which is more forgiving but then doesn’t force developers to use types which is the point of TypeScript.
Type Inference
If a variable is declared and initialised on one line TypeScript will try to infer, guess, the type of a variable by how it’s declared, for example:
Copylet answer = 42;
answer = "42";
TypeScript inferred that the type of answer was number by the fact we initialised it with a number. When we later on try to assign a string to answer
it throws an error.
Copyerror TS2322: Type 'string' is not assignable to type 'number'.
Types for External Libraries
This is all fine for code that’s written in TypeScript and has types.
What if you wanted to use code that wasn’t written in TypeScript or which you are not going to include as TypeScript and compile yourself.
We can use something called an ambient type definition.
This is a file that contains meta-data about the types in another library, a meta-type file.
This repository (https://github.com/DefinitelyTyped/DefinitelyTyped) contains type definitions for some of the most popular third-party JavaScript libraries.
To use them in a file we simply:-
-
Download the associated type file, for example
jquery.d.ts
. -
In the TypeScript file where we want to use the third-party library, add this to the top of the file:
Copy/// <reference path="jquery.d.ts" />
@types
That’s a bit cumbersome so since TypeScript version 2.0 we can use the @types
npm packages instead.
- All the type definitions are now available in the npm scope
@types
. Which means if the types exist we can install it like so
Copynpm install --save @types/angular
The above are the type definitions for AngularJS (Angular version 1.x).
If you were to import angular
into your project like so:
Copyimport * as angular from "angular";
Then even though AngularJS was written in JavaScript without type information, the extra type information in @types/angular is enough for TypeScript to treat it as if it was written in TypeScript and give you type errors etc…​
Summary
With transpile-time type checking TypeScript can help uncover bugs much earlier and faster than if they were to manifest at run-time.
Using types is optional but highly recommended by the Angular team.
If using third-party libraries that have already been transpiled into JavaScript, TypeScript can still perform transpile-time type checking if we include the type definition file for the library.
Listing
Copy"use strict";
// Core
let decimal: number = 6;
let done: boolean = false;
let color: string = "blue";
let list: number[] = [1, 2, 3];
let list2: Array<number> = [1, 2, 3];
// Function
let fun: Function = () => console.log("Hello");
function returnNumber(): number {
return 1;
}
// Void
function returnNothing(): void {
console.log("Moo");
}
// Enum
enum Direction {
Up,
Down,
Left,
Right
}
let go: Direction;
go = Direction.Up;
// Class
class Person1 {
}
let person: Person1;
let people: Person1[];
// Any
let notsure: any = 1;
notsure = "hello"; // This is fine since we don't do type checking with any
// Type Assertion
let value: any = "Asim Hussain";
let len: number = (<string>value).length;
// Generics
class Audio1 {
}
class Video {
}
class Post<T> {
content: T;
}
let audioPost: Post<Audio1>;
let videoPost: Post<Video>;
Caught a mistake or want to contribute to the book? Edit this page on GitHub!

Advanced JavaScript
This unique course teaches you advanced JavaScript knowledge through a series of interview questions. Bring your JavaScript to the 2021's today.
Copy[🌲,🌳,🌴].push(🌲)If you find my courses useful, please consider planting a tree on my behalf to combat climate change. Just $4.50 will pay for 25 trees to be planted in my name. Plant a tree!