Typescript
What is it for?
- it adds types to Javascript
- statically analysable code
- IDE autocompletion support
- easy refactoring
- type correctness

What's different?
- .ts file extension instead of .js
- compiled
- needs type definitions
for using external libraries
Install typescript
sudo npm install -g typescript
Initialize typescript
tsc --init
tsconfig.json
- configuration for typescript compiler
- for node use "target"="es6"
Typescript hello world
- create index.ts
- console.log('Hello world')
- run tsc
So... where are those types?
Basic types
- boolean
- number
- string
- array
- any
- unknown
- null, undefined
- void, never
How to use them?
let myNumericVariable: number = 5;
let myString: string = 'hello';
let myArray: string[] = ['hello', 'hi'];
let myArray: Array<string> = ['hello', 'hi'];
And in functions...
function convertToUppercase(input: string): string {
return input.toUpperCase();
}
function createPerson(id: number, firstName: string, lastName: string): {id: number, name: string} {
return {
id,
name: `${firstName} ${lastName}`,
};
}
Let's make a calculator
- initialize and configure typescript
- implement functions for:
- addition
- subtraction
- sum of numbers in array
Modules
Modules in typescript
- similar to nodejs modules
- export
- import
- but different syntax
Export
import { calculateSum } from './my-file';
let result: number = calculateSum([1,2,3])
Import
export function calculateSum(numbers: number[]): number {
return numbers.reduce((a, b) => a + b)
}
Export default
import renamedSum from './my-file';
let result: number = renamedSum([1,2,3]);
Import
export default function calculateSum(numbers: number[]): number {
return numbers.reduce((a, b) => a + b)
}
- only one default export per module
Try it out
- move calculation functions to separate file (calculations.ts)
- use import/export
- create const for PI = 3.14 to a pi.ts and export it as default export
Importing node libraries
const lodash = require('lodash');
// becomes now:
import lodash from 'lodash';
You will also need type definitions for lodash
What is type definition?
- file containing description of all functions, classes and objects used in the library
- describes only shape, no implementation
- .d.ts extension
- https://github.com/DefinitelyTyped/DefinitelyTyped
- install it using:
- npm install @types/lodash --save-dev
Let's use lodash in Typescript
- create array of people with id and name
- use lodash.find to find person by id
- initialize and configure typescript
- npm install @types/lodash --save-dev
const people = [
{
id: 1,
name: 'Peter'
},
{
id: 2,
name: 'Rachel'
},
{
id: 3,
name: 'John'
},
{
id: 4,
name: 'Tim'
},
{
id: 5,
name: 'Zed'
}
];
How about person object?
const people = [
{
id: 1,
name: 'Peter'
},
{
id: 2,
name: 'Rachel'
},
{
id: 3,
name: 'John'
},
{
id: 4,
name: 'Tim'
},
{
id: 5,
name: 'Zed'
}
];
Let's define Person
interface Person {
id: number;
name: string;
}
Interface
- describes the shape of object
- no implementation
- not included in transpiled code
interface Person {
id: number;
name: string;
age?: number;
shoutOnSomebody(name: string): string;
}
function createPerson(id: number, firstName: string, lastName: string)
: {id: number, name: string} {
return {
id,
name: `${firstName} ${lastName}`,
};
}
// becomes this:
interface Person {
id: number;
name: string;
}
function createPerson(id: number, firstName: string, lastName: string): Person {
return {
id,
name: `${firstName} ${lastName}`,
};
}
Use Person as return type
Known type under any property
interface Person {
name: string;
age: number;
}
interface RandomKeys {
[key: string]: Person
}
let item: RandomKeys = {
martin: {
name: 'Martin',
age: 32
},
homer: {
name: 'Homer',
age: 50
}
}
console.log(item.martin.name)
console.log(item['martin'].name)
Describe a function
interface PrintFunction {
(text: string): void;
}
let printer: PrintFunction;
printer = (text) => console.log(text)
printer = (text) => console.error(text)
Interfaces excercise
- define interface for a calculator
- add(a, b) → number
- subtract(a, b) → number
- PI = 3.14
- create an object which fits such interface
let calculator: Calculator = {...}
Classes
- same as ES6 classes
- encapsulate behaviour
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
sayName() {
console.log(`My name is ${this.name}`);
}
}
Constructor shortcut
- defines property right in the constructor
class Animal {
constructor(public name: string) {
}
sayName() {
console.log(`My name is ${this.name}`);
}
}
Usage
let dog = new Animal('Lassie');
let mouse = new Animal('Mickey');
dog.sayName();
mouse.sayName();
- we create instance of class
Class inheritance
- class may inherit properties and methods from another class
- parent class should be always more general
class Dog extends Animal {
constructor(name: string) {
super(name);
}
bark() {
console.log(`Bark!`);
}
}
public / private / protected
- for both properties and methods
- limits access from outside
-
public
- is default
- everything may access the property
-
private
- accessible only from the class
-
protected
- accessible only from class and its derived classes
Let's describe an army
- soldier with sword and shield
- archer with a bow
- knight on a horse with sword
- everyone has some coordinates [X, Y]
- abilities
- use weapons
- move
Union type
let value: number | string = 5; // ok
value = 'hi'; // also ok
let pet: Dog | Turtle | Cat;
Types
Type
- you can define your own types
- similar to interface
- interface describes object-like stuff
- type can use also primitive types
type Answer = 'yes' | 'no';
let x: Answer;
type Person = {
name: string;
age: number;
}
type AnswerList = {
[key in Answer]: boolean;
}
Type
- work with primitive types
- more flexible (union etc)
- sometimes don't appear in error messages
Interface
- redefinition extends
- for object types
- always appear with original name in error messages
Generics
let value: Array<number> = [5, 2, 4];
// generic function
function print<T>(item: T) {
console.log(item);
}
print<string>('hi');
let x = print(4);
Create generic class
class Bucket<T> {
items: T[] = [];
insert(item: T) {
this.items.push(item);
}
}
let myBucket = new Bucket<string>();
myBucket.insert('hello');
Partial generic class
interface Person {
age: number;
name: string;
}
let obj: Partial<Person> = {
age: 32
}
- part of util classes
Create a map
- store data under keys
- methods
- set(key, value)
- get(key)
- has(key)
- entities() - gives all keys
- print() - prints everything inside the map
Decorators
@Component({
selector: 'app-home',
template: '<h1>Hello</h1>'
})
class HomeComponent {
}
- not part of JS yet (stage 2)
- adds metadata
Debugging
Debug typescript in VS Code
- enable "sourceMap": true in tsconfig.json
- switch to debug panel
- hit the settings icon - launch.json opens
- press Add Configuration
- choose Node.js: Launch Program
- set "program" property to index.ts
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceRoot}/index.ts",
"outFiles": [
"${workspaceRoot}/**/*.js"
]
}
Alpiq Typescript
By Martin Nuc
Alpiq Typescript
- 281