AskDB
·8 min read

TypeScript Guide: Types and Best Practices

TypeScript adds static typing to JavaScript. It catches bugs at compile time, improves IDE support, and makes large codebases maintainable.

Basic Types

let name: string = "Alice";
let age: number = 30;
let active: boolean = true;
let items: string[] = ["a", "b"];
let data: [string, number] = ["Alice", 30]; // tuple
let value: any = "anything";
let nothing: void = undefined;
let never: never; // never returns

Interfaces

interface User {
  id: number;
  name: string;
  email: string;
  age?: number;           // optional
  readonly createdAt: Date; // readonly
}

interface Admin extends User {
  role: "admin" | "superadmin";
  permissions: string[];
}

Type Aliases

type ID = string | number;
type Status = "active" | "inactive" | "banned";
type Point = { x: number; y: number };
type Callback = (data: string) => void;

Generics

function identity<T>(value: T): T {
  return value;
}

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

interface ApiResponse<T> {
  data: T;
  status: number;
  message: string;
}

type UserResponse = ApiResponse<User>;
type ListResponse = ApiResponse<User[]>;

Utility Types

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

// Required - all properties required
type RequiredUser = Required<User>;

// Pick - select specific properties
type UserName = Pick<User, "name" | "email">;

// Omit - exclude properties
type UserWithoutId = Omit<User, "id">;

// Record - map keys to values
type Roles = Record<string, string[]>;

// Exclude / Extract
type StringOrNumber = string | number | boolean;
type OnlyString = Exclude<StringOrNumber, number>; // string | boolean

Functions

function add(a: number, b: number): number {
  return a + b;
}

const greet = (name: string): string => {
  return `Hello, ${name}`;
};

// Function overloads
function format(value: string): string;
function format(value: number): string;
function format(value: string | number): string {
  return String(value);
}

Classes

class Animal {
  constructor(
    public name: string,
    private age: number,
    protected species: string
  ) {}

  greet(): string {
    return `I am ${this.name}`;
  }
}

Type Guards

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

function process(value: string | number) {
  if (isString(value)) {
    console.log(value.toUpperCase()); // TS knows it's string
  } else {
    console.log(value.toFixed(2)); // TS knows it's number
  }
}

Best Practices

  • Prefer interfaces for object shapes, types for unions/intersections
  • Use unknown instead of any
  • Enable strict mode in tsconfig.json
  • Use const assertions for literal types: as const
  • Prefer readonly arrays and properties when data should not mutate