← ClaudeAtlas

typescript-best-practiceslisted

TypeScript best practices. Use when reading or editing any .ts or .tsx file.
bendusz/pm-skill · ★ 2 · AI & Automation · score 72
Install: claude install-skill bendusz/pm-skill
# TypeScript best practices Apply the **type-system-discipline** principle skill first; this skill grounds it in TypeScript syntax. | Rule | Summary | |------|---------| | Discriminated unions | Model variants with a `kind` literal discriminant so impossible states can't be represented. No optional-field bags. | | Branded types | Brand primitives with `& { readonly __brand: "X" }` so they can't be mixed up. Validate once at creation. | | Constructive modeling | Build the shape so the illegal value can't be constructed. `[T, ...T[]]` for non-empty, `[T, T][]` for even length, `start` plus `duration` for a range. Not a runtime guard, not a wish for refinement types. | | Simplest total type | Keep `T[]` while every operation on it stays total. Strengthen to `NonEmpty<T>` only where the loose type forces `!`, a cast, or a "should never happen" throw. | | `unknown` over `any` | External data is `unknown`. `any` disables type checking everywhere it touches. | | No `as` casts | Every `as` is a runtime crash waiting. Cast only after validation. | | Narrowing hierarchy | Discriminant switch > `in` operator > `typeof`/`instanceof` > user-defined type guard > `as`. | | Type guards | Must verify the claim. A lying guard is worse than `as` because the bug hides behind a name that says it's safe. Name them `isX` or `hasX`. | | Exhaustiveness | Inline `const _exhaustive: never = x;` in default arms so the compiler errors when a new variant is added. | | `satisfies` over `as` | Validates t