Free developer tools and practical guides for SQL, data workflows, and debugging.
AAskDBSQL & Data Toolkit

TypeScript Guide: Types and Best Practices

·8 min read

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