Skip to main content

TypeScript

TypeScript is a superset of JavaScript developed by Microsoft that adds static typing and other modern features to improve the quality, maintainability and scalability of your code. This means that all valid JavaScript code is also valid TypeScript code, and TypeScript also gives you additional tools.

1. Why use TypeScript?​

JavaScript is a flexible and dynamic language, but that flexibility can lead to errors that are hard to detect. TypeScript helps you prevent them before running the code thanks to static typing and more powerful development tools.

Main advantages:

  • Static typing (prevents common type errors).
  • Autocompletion and better support in editors such as VS Code.
  • Error detection at compile time.
  • Use of modern JavaScript features even before they are supported by all browsers.
  • Code that is easier to maintain.

Example of a problem in JavaScript:

Why use TypeScript
function sumar(a, b) {
return a + b;
}

console.log(sumar(5, "10")); // "510" instead of 15

Solution in TypeScript:

Why use TypeScript (solution)
function sumar(a: number, b: number): number {
return a + b;
}

// console.log(sumar(5, "10")); // Error: Argument of type 'string' is not assignable to parameter of type 'number'.
console.log(sumar(5, 10)); // 15

2. Basic installation and setup​

2.1 Global installation​

We need Node.js and npm installed.

npm install -g typescript

Verify the installation:

tsc -v

2.2 Initialize a project with TypeScript​

Initialize a project with TypeScript
mkdir proyecto-ts
cd proyecto-ts
npm init -y
npm install typescript --save-dev

Generate the tsconfig.json configuration file:

npx tsc --init

This will create a file with many commented options. The most important ones to get started:

Initialize a project (solution)
{
"compilerOptions": {
"target": "es6", // JS version to generate
"module": "commonjs", // Module system
"outDir": "./dist", // Output folder
"rootDir": "./src", // Source code folder
"strict": true, // Enable all strict checks
"esModuleInterop": true // Better module compatibility
}
}

Recommended project structure:

proyecto-ts/
├── src/
│ └── index.ts
├── dist/
├── package.json
└── tsconfig.json

2.3 Compile and run​

To compile:

npx tsc

This will generate .js files in dist/.

To run:

node dist/index.js

If we want to compile and run in a single step, we can use ts-node:

npm install -D ts-node
npx ts-node src/index.ts

3. Basic types in TypeScript​

TypeScript adds static types that let us define what kind of data we expect.

Basic types in TypeScript
let nombre: string = "Kevin";
let edad: number = 25;
let activo: boolean = true;
let indefinido: undefined = undefined;
let nulo: null = null;
let cualquiera: any = "Hello"; // Avoid whenever possible

Arrays:

Basic types in TypeScript (solution)
let numeros: number[] = [1, 2, 3];
let letras: Array<string> = ["a", "b", "c"];

Tuples:

Basic types in TypeScript (3)
let persona: [string, number] = ["Kevin", 25];

Enums:

Basic types in TypeScript (4)
enum Color {
Rojo = "ROJO",
Verde = "VERDE",
Azul = "AZUL"
}

let colorFav: Color = Color.Verde;
console.log(colorFav); // "VERDE"

Union types:

Basic types in TypeScript (5)
let id: string | number;
id = "ABC123";
id = 42;

Type aliases:

Basic types in TypeScript (6)
type ID = string | number;
let usuarioID: ID = 101;

4. Functions in TypeScript​

We can type parameters and return values.

Functions in TypeScript
function saludar(nombre: string): string {
return `Hello, ${nombre}`;
}

console.log(saludar("Kevin"));

Optional and default parameters:

Functions in TypeScript (solution)
function multiplicar(a: number, b: number = 2, mensaje?: string): number {
if (mensaje) console.log(mensaje);
return a * b;
}

console.log(multiplicar(3));
console.log(multiplicar(3, 4, "Calculating..."));

Arrow functions:

Functions in TypeScript (3)
const dividir = (a: number, b: number): number => a / b;

5. Interfaces and Objects​

Interfaces define the shape of an object.

Interfaces and Objects
interface Usuario {
id: number;
nombre: string;
activo?: boolean; // optional
}

let user1: Usuario = {
id: 1,
nombre: "Kevin"
};

Interfaces with functions:

Interfaces and Objects (solution)
interface Operacion {
(a: number, b: number): number;
}

const sumar: Operacion = (x, y) => x + y;
console.log(sumar(5, 3));

6. Classes in TypeScript​

Classes in TypeScript
class Persona {
private nombre: string;
protected edad: number;
public activo: boolean;

constructor(nombre: string, edad: number, activo: boolean) {
this.nombre = nombre;
this.edad = edad;
this.activo = activo;
}

saludar(): string {
return `Hello, I am ${this.nombre}`;
}
}

const p1 = new Persona("Kevin", 25, true);
console.log(p1.saludar());

Inheritance:

Classes in TypeScript (solution)
class Estudiante extends Persona {
curso: string;
constructor(nombre: string, edad: number, activo: boolean, curso: string) {
super(nombre, edad, activo);
this.curso = curso;
}
}

7. Modules in TypeScript​

Export:

utils.ts
// file: utils.ts
export function sumar(a: number, b: number): number {
return a + b;
}

Import:

index.ts
// file: index.ts
import { sumar } from "./utils";
console.log(sumar(3, 4));

8. Advanced types​

Generics:

Generics, just like in Java, let us create functions and classes that can work with different data types without losing type safety. In them we specify a generic type denoted by <T>, which we can use in place of a specific type.

Advanced types
function identidad<T>(valor: T): T {
return valor;
}

console.log(identidad<string>("Hello"));
console.log(identidad<number>(123));

The previous example shows a function that receives a value of generic type T and returns it without modifying it. This makes the function flexible and reusable with different data types.

Intersection types:

These types let you combine multiple types into a single one, creating a new type that has all the properties of the combined types.

Advanced types (solution)
interface A { a: string; }
interface B { b: number; }
// Same as interface C { a: string; b: number; }

type AB = A & B;
let obj: AB = { a: "Hello", b: 42 };

9. Running in the browser​

To use TypeScript in the browser:

  1. Compile to JavaScript.
  2. Include the .js file in the HTML.

Example:

src/app.ts
// src/app.ts
const mensaje: string = "Hello from TS";
console.log(mensaje);
index.html
<!-- index.html -->
<script src="dist/app.js"></script>

10. Interface vs Type Alias​

In TypeScript, both interfaces and type aliases are used to define types, but they have some key differences:

  • Interfaces: Used mainly to define the shape of an object. They can be extended and are ideal for defining clear contracts between different parts of the code.
Interface vs Type Alias
interface Usuario {
id: number;
nombre: string;
}
  • Type Aliases: Used to define more complex types, including unions, tuples and primitive types. They cannot be extended like interfaces, but they are more flexible.
Interface vs Type Alias (solution)
type ID = string | number;
type Usuario = {
id: ID;
nombre: string;
};

Example: Something you can do with type but not with interface​

type aliases let you define type unions, something that is not directly possible with interface.

Example: Something you can do
type Resultado = string | number;

let respuesta: Resultado;
respuesta = "Success";
respuesta = 42;

// This cannot be done with `interface`.

In this case, Resultado can be a string or a number, which makes it more flexible for certain scenarios. Interfaces, on the other hand, are designed to describe the shape of objects and do not support type unions.


11. Recommendations​

  • Enable strict in tsconfig.json.
  • Avoid using any.
  • Use interfaces and types to define clear contracts.
  • Take advantage of the editor's autocompletion and static analysis.
  • Compile frequently to detect errors early.

Self-Assessment Quiz​

Cargando cuestionario...