The Definitive Guide to TypeScript: From Zero to Advanced

- Andrés Cruz

ES En español

The Definitive Guide to TypeScript: From Zero to Advanced

TypeScript has established itself not only as a useful tool but as the industry standard. According to data from GitHub, TypeScript has become the number one language on the platform, even surpassing the growth of Python. This boom is largely due to its massive adoption in the Artificial Intelligence ecosystem, where frameworks and SDKs like Mantra or agentic workflows use it by default to guarantee code robustness.

1. Introduction: What is TypeScript?

TypeScript is a programming language developed by Microsoft, defined as a superset of JavaScript. The logic is simple:

JavaScript + Types = TypeScript

This language offers full backward compatibility: all JS code is valid TS code. However, TypeScript adds a syntax layer to define types, allowing errors to be detected during development rather than when the end user is using the application. As proof of its power, the Visual Studio Code editor is built entirely with TypeScript, which explains why it offers such exceptional native support.

2. Theoretical Foundations: Deep Diving into Typing

As a senior developer, you must understand that the difference between JS and TS is not "cosmetic," but structural:

ConceptJavaScript (JS)TypeScript (TS)
CheckingDynamic: At runtime.Static: At compile time.
ConversionWeak: Allows implicit type coercion.Strong: Prevents unexpected conversions.

The double(n) function example

In JavaScript, a function that multiplies a value by two can be "dangerous":

// In JavaScript 
function double(n) { 
  return n * 2;
} 
double("4"); // Returns 8 (Implicit coercion: JS transforms the string into a number) // In TypeScript 
function double(n: number) { 
  return n * 2;
} 
double("4"); // Error: Type 'string' is not assignable to type 'number'.

TS prevents code from running with incorrect types, saving you from silent bugs that in JS you would only see when something explodes in the browser.

3. Compile Time vs. Runtime Behavior

A common mistake is thinking that TypeScript protects your code while it is running. It does not. TS types "disappear" (a process called type erasure) after compilation. The browser or Node.js only see pure JavaScript.

TypeScript does not perform runtime validations. If you receive data from an external API via JSON.parse or user inputs, TypeScript cannot magically know what is there. In these cases, it is mandatory to perform additional validations (narrowing) or use schema libraries to ensure data integrity.

4. Type Inference and Primitives

Inference: The compiler "guesses"

TypeScript has the ability to deduce the type without you writing it:

  • With let: If you declare let name = "Andrew", TS infers the general type string.
  • With const: If you declare const name = "Andrew", TS infers the literal type "Andrew", since the value will never change.

Primitive Types

  • string, number, boolean, null, undefined.
  • symbol: For unique identifiers.
  • bigint: For extremely large numbers. Technical note: bigint literals must end with the suffix n (e.g., 100n).

Union Types

They allow a variable to be of several possible types.

let age: number | null = 30; 
age = null; // Valid

5. Arrays and Tuples

Array Syntax

  1. Simple (type[]): Recommended for primitive or simple types (e.g., number[]).
  2. Generic (Array<type>): Recommended for complex types or when working with generics.

Tuples: Fixed-length structures

Tuples are arrays where we know exactly how many elements there are and what type occupies each position.

  • Labeled tuples: Improve contract readability.
  • Rest elements: For collections with a fixed base.
  • Readonly: Ideal for configurations that should not mutate.

6. Objects and Structural Typing

Structural Typing (Duck Typing)

Unlike languages like Java (nominal typing), TypeScript uses Structural Typing. This means TS cares about the shape of the object, not its name or class. If an object has the required properties, it is accepted. "If it walks like a duck and quacks like a duck, it's a duck."

Type Aliases and Modules

We can define reusable contracts and organize them into files (e.g., types.ts) using export and import type.

export type User = {
  readonly id: string; // No modificable
  name: string;
  email?: string; // Opcional
};
// Index Signatures para llaves dinámicas (traducciones, diccionarios)
type Dictionary = {
  [key: string]: string;
};

7. Intersections and Literal Types

  • Intersection Types (&): Combine multiple types. Useful for complex entities.
  • Literal Types: Restrict values to exact options.

8. Special Types: The Security Quadrant

To handle uncertainty, TS proposes four key types that form the "Security Quadrant":

  • any: The "panic button." Disables all checks. It is contagious like an ex: if a variable is any, everything it touches will become any. Always avoid it, except in critical JS to TS migrations.
  • unknown: The safe alternative to any. You can assign anything to it, but TS won't let you operate with it until you perform narrowing (type checking). It is the ideal type for JSON.parse.
  • void: Indicates that a function returns nothing useful (even if it technically returns undefined).
  • never: Represents impossible values or functions that never end (infinite loops, exceptions).

9. Functions in TypeScript

We can type parameters (with default values or rest) and the return type:

type Operation = (a: number, b: number) => number;
const multiply: Operation = (a, b) => a * b;
function log(message: string, userId?: string): void {
  console.log(`${userId ?? 'Anon'}: ${message}`);
}

10. Advanced Narrowing

It is the technique of reducing a broad type to a specific one to be able to operate safely.

  • typeof: For primitives (string, number).
  • Truthiness: To discard null or undefined.
  • in: To check if a property exists in an object.
  • instanceof: For classes or objects like Date.

Example of narrowing by exclusion:

function move(animal: Fish | Bird | Dog) {
  if ("swim" in animal) {
    animal.swim(); // TS sabe que es Fish
  } else if ("fly" in animal) {
    animal.fly();  // TS sabe que es Bird
  } else {
    animal.bark(); // Por exclusión, TS sabe que aquí solo puede ser Dog
  }
}

Expert Pro-Tip: Install the "Pretty TypeScript Errors" extension in VS Code. It converts TS errors (which sometimes look like hieroglyphics) into visual and readable descriptions that will save your life.

11. Interfaces: The object contract

Interfaces are similar to type aliases, but they are designed to define the shape of objects and classes.

  • Extension: They use extends to inherit.
  • Declaration Merging: If you declare the same interface twice, TS merges them. This is vital for extending third-party libraries or adding properties to the window object.
  • Implementation: Classes use implements to fulfill contracts.
interface Player { play(): void; } 
class VideoPlayer implements Player { play() { /* ... */ } }

12. Modern execution with Node.js 24+

As of Node.js 24, the environment can run .ts files natively. This is excellent for quick scripts, development tools, and prototyping without configuring tsc. Nonetheless, for complex production projects, a solid build process is still recommended to optimize the resulting code.

Learn TypeScript from scratch with this free Full Stack Bootcamp course. Master the JavaScript superset, static typing, interfaces, narrowing, and prepare for the future with AI.

I agree to receive announcements of interest about this Blog.

Andrés Cruz

ES En español