TypeScript: Mastering Static Typing

Learn TypeScript and make your JavaScript code safer and more robust


TypeScript: Mastering Static Typing
1 Loading...

TypeScript: Mastering Static Typing

TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. Developed by Microsoft and released in 2012, it adds optional static typing and advanced object-oriented features to JavaScript, making large-scale application development safer and more productive.

Note: TypeScript is built on JavaScript. If you need to review the fundamentals, check out our Complete JavaScript Guide before continuing.

Why TypeScript?

TypeScript offers significant benefits for teams and projects of any size:

  1. Compile-Time Error Detection - Find bugs before running the code
  2. Enhanced IntelliSense - Smart autocomplete and inline documentation
  3. Safe Refactoring - Rename variables and functions with confidence
  4. Implicit Documentation - Types serve as living documentation
  5. Scalability - Keep large projects organized and safe
  6. Gradual Adoption - Migrate from JavaScript incrementally

Basic Types

Primitive Types

// Simple types
let name: string = "Maria";
let age: number = 25;
let active: boolean = true;
let nullValue: null = null;
let undefinedValue: undefined = undefined;

// Arrays
let numbers: number[] = [1, 2, 3, 4, 5];
let names: Array<string> = ["Ana", "Pedro", "Carlos"];

// Tuples
let coordinate: [number, number] = [10, 20];
let record: [string, number, boolean] = ["Maria", 25, true];

// Enum
enum Status {
  Pending = "PENDING",
  Approved = "APPROVED",
  Rejected = "REJECTED"
}

let orderStatus: Status = Status.Pending;

Advanced Types

// Union Types
type ID = string | number;
let userId: ID = "abc123";
userId = 42; // Also valid

// Intersection Types
type Person = { name: string };
type Employee = { role: string };
type PersonEmployee = Person & Employee;

// Literal Types
type Direction = "north" | "south" | "east" | "west";
let direction: Direction = "north";

// Template Literal Types
type EventName = `on${Capitalize<string>}`;

// Nullable Types
let optionalValue: string | null = null;
optionalValue = "Defined value";

Interfaces vs Types

// Interface - ideal for objects and classes
interface User {
  id: number;
  name: string;
  email: string;
  readonly createdAt: Date;
  address?: Address; // Optional property
}

interface Address {
  street: string;
  city: string;
  country: string;
}

// Interface extension
interface Admin extends User {
  permissions: string[];
  level: "junior" | "senior" | "master";
}

// Type alias - more flexible
type Result<T> = 
  | { success: true; data: T }
  | { success: false; error: string };

type Callback<T> = (data: T) => void;

Generics

// Generic function
function first<T>(array: T[]): T | undefined {
  return array[0];
}

const firstNumber = first([1, 2, 3]); // number
const firstString = first(["a", "b", "c"]); // string

// Generic class
class Stack<T> {
  private items: T[] = [];

  push(item: T): void {
    this.items.push(item);
  }

  pop(): T | undefined {
    return this.items.pop();
  }

  peek(): T | undefined {
    return this.items[this.items.length - 1];
  }
}

// Constraints
interface WithId {
  id: number;
}

function findById<T extends WithId>(items: T[], id: number): T | undefined {
  return items.find(item => item.id === id);
}

// Utility Types
type ReadonlyUser = Readonly<User>;
type PartialUser = Partial<User>;
type UserWithoutAddress = Omit<User, "address">;
type OnlyNameEmail = Pick<User, "name" | "email">;

Typed Functions

// Function with explicit types
function calculateDiscount(
  price: number,
  percentage: number
): number {
  return price * (1 - percentage / 100);
}

// Typed arrow function
const multiply = (a: number, b: number): number => a * b;

// Function overloading
function process(value: string): string;
function process(value: number): number;
function process(value: string | number): string | number {
  if (typeof value === "string") {
    return value.toUpperCase();
  }
  return value * 2;
}

// Type guards
function isString(value: unknown): value is string {
  return typeof value === "string";
}

function formatValue(value: unknown): string {
  if (isString(value)) {
    return value.trim();
  }
  return String(value);
}

Classes with TypeScript

abstract class Entity {
  constructor(
    public readonly id: string,
    public createdAt: Date = new Date()
  ) {}

  abstract validate(): boolean;
}

class Product extends Entity {
  constructor(
    id: string,
    public name: string,
    public price: number,
    private _stock: number = 0
  ) {
    super(id);
  }

  get stock(): number {
    return this._stock;
  }

  set stock(value: number) {
    if (value < 0) {
      throw new Error("Stock cannot be negative");
    }
    this._stock = value;
  }

  validate(): boolean {
    return this.name.length > 0 && this.price > 0;
  }

  applyDiscount(percentage: number): number {
    return this.price * (1 - percentage / 100);
  }
}

// Implementing interfaces
interface Serializable {
  toJSON(): string;
}

class Item implements Serializable {
  constructor(public name: string) {}

  toJSON(): string {
    return JSON.stringify({ name: this.name });
  }
}

Project Configuration

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

Learning Checklist

  • Master primitive types and arrays
  • Understand interfaces and type aliases
  • Learn generics and constraints
  • Study utility types (Partial, Readonly, Pick, Omit)
  • Practice type guards and narrowing
  • Configure projects with tsconfig.json
  • Migrate an existing JavaScript project

Common Mistakes to Avoid

  • Using any everywhere → Use unknown or specific types
  • Ignoring compilation errors → Fix all type errors
  • Not using strict mode → Always enable strict: true
  • Duplicating types → Use utility types to derive types

Essential Resources

Quote

“TypeScript is JavaScript that scales.” - Anders Hejlsberg, TypeScript creator


TypeScript transforms the way you write JavaScript. Invest time learning its features and your productivity will increase significantly!