Skip to main content

Getting Started

Introduction

TypeScript (TS) is essential typed JavaScript. So JavaScript with types. Also it is a superset of JavaScript, which means that you can use the latest features of JavaScript and transpile your TypeScript down to your target JavaScript version (e.g. es2016). Try it out here. So we don't ship TypeScript because the browser only understands JavaScript. Also, when the TypeScript compiler translates the code to JavaScript it does not perform any performance optimizations!

To summarize the benefits of TypeScript, essentially it helps us to catch errors at build-time and not when it is too late (runtime) by using type annotations to analyze our code. The errors I am talking about are typos (e.g. wrong prop name) or a wrong order of method parameters, so rather trivial stuff, but unfortunately these types of errors happen quite frequently. So it is really great that we can spot these errors the moment we finished typing in our code editor, right?

And as JavaScript is omnipresent nowadays, you can use TypeScript for Web Development, e.g. with React or Angular, for Mobile Development (with React Native) and Backend Development (node.js).

Setup

To be able to use TypeScript you have to install the following two libraries: npm i -g typescript ts-node

ts-node is the TypeScript version of node. So by using ts-node some-file.ts you can execute a TypeScript file. You can manually transpile TS -> JS via the TS-Compiler tsc.

So this: tsc file.ts (compile) then node file.js (execute) is equivalent to ts-node file.ts. Later on you might use a bundler like webpack or parcel-bundler to take care of transpiling and performing code optimizations, like tree-shaking or code-splitting. Angular and React use Webpack under the hood, but if you use something else, I'd say that Parcel is easier to start with, but Webpack is the de-factor standard bundler for the web which can be extended with various plugins. You can always start with parcel and in case you need something special, there is likely a webpack plugin, you just move to webpack.

You will probably also configure the TypeScript Compiler via the tsconfig.json to fit your needs (e.g. target JS version).

Type Annotations and Type Inference

There are two important concepts, namely type annotation, done by us (the developer), and type inference done by the TypeScript Compiler. These concepts work differently for variables, functions and objects.

Type Annotations

The syntax for variables is: [let | const | var] <name>: <type> = <value>, e.g. const age: number = 42. A type can be a primitive type like number or string, but can also refer to an object type, like Date or an interface. The type can also be an array, like let colors: string[] = ['red', 'green', 'blue'].

The syntax for classes is: [let | const | var] <name>: <type> = <object>, e.g. const ludwig: Person = new Person(). And for an object literal it is:

let point: { x: number; y: number } = {
x: 10,
y: 20
};

A lambda function is annotated like so (input/params + output/return value):

const doSomething: (action: string) => void = (action: string) => {
console.log(`performing ${action}`);
};

Destructured params are annotated like so (destructured values are always separated from type annotations):

const calculateSomething = ({ x, y }: { x: number, y: number}): number => {
return x + y;
};

const coords: { x: number, y: number} = { x: 42, y: 42 };
calculateSomething(coords);

Type Inference

Types can also be inferred from the value. E.g. the compiler knows that the type of age in const age = 42 is a number. So one needs to know when to rely on type inference and when not.

Only when variable declaration (const age) and variable initialization (= 42) happen on the same line (const age = 42;) then TypeScript will figure out the type for us, so there is no need for us to annotate the variable.

So we really should just use type annotation when:

  • we declare and initialize a variable on different lines (not the same line)
  • the type of the variable cannot be inferred (e.g. a variable can have multiple types like const preferredWayOfContact: Email | Phone | Mail)
  • a function returns any and we want to clarify the value (e.g. JSON.parse() returns any)

Type inference for functions for example works only for the return value, but not for its parameters.

And use type inference always as otherwise we would just add unnecessary annotation to the code and therefore make it less readable.

Type Definition Files

When working with JavaScript libraries in TypeScript you might encounter an error when importing functionality from some library. The error would tell you to install the typings of the library at hand, usually by trying to run npm i @types/<library-name>.

The thing is, sometimes typings or a type definition file (*.d.ts) is included with the library and sometimes you have to install it manually. For the vast majority of popular libraries there are already typings present (see DefinitelyTyped), so you don't really need to worry much about it.

Study Material