TypeScript

JavaScript with static typing for robust applications

TypeScript

TypeScript is a superset of JavaScript that adds static typing. It allows you to catch errors before running the code.

Installation

npm install -g typescript

Typing Basics

Primitive Types

// Basic types
let name: string = "TechYouHigh";
let age: number = 25;
let isActive: boolean = true;

// Arrays
let numbers: number[] = [1, 2, 3];
let fruits: Array<string> = ["apple", "banana"];

// Tuple
let coordinates: [number, number] = [10, 20];

// Any (to avoid)
let variable: any = "anything";

Interfaces

interface User {
  id: number;
  name: string;
  email: string;
  age?: number; // Optional property
  readonly createdAt: Date; // Read-only
}

const user: User = {
  id: 1,
  name: "John Doe",
  email: "john@example.com",
  createdAt: new Date(),
};

Custom Types

// Type alias
type ID = string | number;
type Status = "active" | "inactive" | "suspended";

// Union types
function showId(id: ID) {
  console.log(`ID: ${id}`);
}

// Literal types
let status: Status = "active";

Typed Functions

// Function with types
function add(a: number, b: number): number {
  return a + b;
}

// Function with optional parameters
function greet(name: string, title?: string): string {
  return title ? `${title} ${name}` : name;
}

// Function with default parameters
function createUser(name: string, role: string = "user") {
  return { name, role };
}

// Function type
type MathOperation = (a: number, b: number) => number;

const multiply: MathOperation = (a, b) => a * b;

Generics

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

const firstNumber = firstElement([1, 2, 3]); // number
const firstText = firstElement(["a", "b"]); // string

// Generic interface
interface Response<T> {
  data: T;
  status: number;
  message: string;
}

const userResponse: Response<User> = {
  data: user,
  status: 200,
  message: "Success",
};

Classes

class Person {
  private id: number;
  public name: string;
  protected age: number;

  constructor(id: number, name: string, age: number) {
    this.id = id;
    this.name = name;
    this.age = age;
  }

  introduce(): string {
    return `My name is ${this.name}`;
  }

  get identifier(): number {
    return this.id;
  }
}

class Employee extends Person {
  constructor(id: number, name: string, age: number, public position: string) {
    super(id, name, age);
  }

  introduce(): string {
    return `${super.introduce()} and I am a ${this.position}`;
  }
}

TypeScript Utilities

// Partial: makes all properties optional
type PartialUser = Partial<User>;

// Required: makes all properties required
type CompleteUser = Required<User>;

// Pick: selects certain properties
type BasicUser = Pick<User, "id" | "name">;

// Omit: excludes certain properties
type UserWithoutEmail = Omit<User, "email">;

// Record: creates an object type
type Roles = Record<string, string[]>;
const permissions: Roles = {
  admin: ["read", "write", "delete"],
  user: ["read"],
};

tsconfig.json Configuration

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

Best Practices

  1. Enable strict mode in tsconfig.json
  2. Avoid any as much as possible
  3. Use interfaces for objects
  4. Type function returns explicitly
  5. Use generics for reusable code

Resources