TypeScript Cheatsheet
Enums
Use this TypeScript reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
Numeric Enums
// Members auto-increment from 0 by default enum Direction { Up, // 0 Down, // 1 Left, // 2 Right, // 3 } // Custom starting value enum Status { Pending = 1, Active, // 2 Inactive, // 3 } // Custom value for each member enum HttpStatus { OK = 200, Created = 201, BadRequest = 400, Unauthorized = 401, NotFound = 404, ServerError = 500, } const dir: Direction = Direction.Up; // 0 const code: HttpStatus = HttpStatus.OK; // 200
String Enums
// Each member must have a string literal value enum Color { Red = "RED", Green = "GREEN", Blue = "BLUE", } enum LogLevel { Debug = "debug", Info = "info", Warn = "warn", Error = "error", } const level: LogLevel = LogLevel.Warn; // "warn" // String enums are NOT reverse-mappable (unlike numeric) // LogLevel["warn"] doesn't give you LogLevel.Warn
Heterogeneous Enums (Avoid)
// Mixing string and number members is allowed but discouraged enum Mixed { No = 0, Yes = "YES", } // Avoid this pattern — it's confusing and rarely useful
Const Enums
// Inlined at compile time — no runtime object generated const enum Axis { X, // 0 Y, // 1 Z, // 2 } let axis = Axis.X; // compiles to: let axis = 0; // Benefit: zero runtime overhead // Tradeoff: can't use Axis as a value (no Object.values(Axis)), can't use with --isolatedModules if from another file const enum Permission { Read = 1 << 0, // 1 Write = 1 << 1, // 2 Execute = 1 << 2, // 4 }
Ambient Enums
// declare enum — describes an enum that exists in another context (e.g., a .d.ts) declare enum ExternalStatus { Active, Inactive, } // declare const enum — for declaration files declare const enum ExternalCode { A = 1, B = 2, }
Enum as Type
enum Suit { Clubs = "CLUBS", Diamonds = "DIAMONDS", Hearts = "HEARTS", Spades = "SPADES", } // Enum type can be used like any type function playCard(suit: Suit): void { console.log(suit); } playCard(Suit.Hearts); // playCard("HEARTS"); // Error — must use enum member // Enum member type type Hearts = Suit.Hearts; // the literal type "HEARTS"
Reverse Mapping (Numeric Enums Only)
enum Direction { Up = 0, Down = 1, } Direction.Up; // 0 Direction[0]; // "Up" ← reverse mapping Direction[Direction.Up]; // "Up" // Not available for string enums enum Color { Red = "RED" } // Color["RED"] — undefined (no reverse map for string enums)
Enum Iteration
enum Role { Admin = "ADMIN", User = "USER", Guest = "GUEST", } // Iterating string enum values Object.values(Role).forEach(r => console.log(r)); // "ADMIN", "USER", "GUEST" // Iterating numeric enum (includes reverse mapping entries — filter needed) enum Status { Active, Inactive } const numericValues = Object.values(Status) .filter((v): v is number => typeof v === "number"); // [0, 1] // Keys of numeric enum const numericKeys = Object.keys(Status) .filter(k => isNaN(Number(k))); // ["Active", "Inactive"]
Enum Member Types and Union
// Each member of a literal enum becomes its own type enum ShapeKind { Circle, Square, } interface Circle { kind: ShapeKind.Circle; radius: number; } interface Square { kind: ShapeKind.Square; side: number; } type Shape = Circle | Square; function area(s: Shape) { switch (s.kind) { case ShapeKind.Circle: return Math.PI * s.radius ** 2; case ShapeKind.Square: return s.side ** 2; } }
Bitwise / Flags Enum Pattern
enum FilePermission { None = 0, Read = 1 << 0, // 1 Write = 1 << 1, // 2 Execute = 1 << 2, // 4 All = Read | Write | Execute, // 7 } // Combine flags const userPerms = FilePermission.Read | FilePermission.Write; // 3 // Check flag function hasPermission(perms: FilePermission, flag: FilePermission): boolean { return (perms & flag) === flag; } hasPermission(userPerms, FilePermission.Read); // true hasPermission(userPerms, FilePermission.Execute); // false // Add flag const newPerms = userPerms | FilePermission.Execute; // 7 // Remove flag const reduced = userPerms & ~FilePermission.Write; // 1
Enum vs as const Object Pattern
// Enum — generates a real runtime object and a type enum DirectionEnum { Up = "UP", Down = "DOWN", } // as const — plain object with no enum overhead; more tree-shakeable const Direction = { Up: "UP", Down: "DOWN", } as const; type Direction = typeof Direction[keyof typeof Direction]; // "UP" | "DOWN" // Usage is nearly identical const go = (dir: Direction) => console.log(dir); go(Direction.Up); // Advantages of as const over enum: // - No runtime enum object bloat (tree-shakeable) // - Works with --isolatedModules // - Integrates seamlessly with string union types // - More predictable in module resolution
Exhaustiveness Checking with Enums
enum Fruit { Apple, Banana, Cherry, } function describe(f: Fruit): string { switch (f) { case Fruit.Apple: return "apple"; case Fruit.Banana: return "banana"; case Fruit.Cherry: return "cherry"; default: const _exhaustive: never = f; // Error if a case is missing return _exhaustive; } }
Enums in Function Parameters and Guards
enum Status { Active = "active", Inactive = "inactive", Pending = "pending", } // Type guard to check if a string is a valid Status function isStatus(val: string): val is Status { return Object.values(Status).includes(val as Status); } // Parse unknown string function parseStatus(val: string): Status { if (!isStatus(val)) throw new Error(`Invalid status: ${val}`); return val; } // Enum as record key const statusLabels: Record<Status, string> = { [Status.Active]: "Active", [Status.Inactive]: "Inactive", [Status.Pending]: "Pending", };