personal-typescript
Installation
SKILL.md
TypeScript and JavaScript Conventions
Framework-agnostic language conventions for any TS/JS code: browser, Node, build tooling, service workers, browser extensions. Framework specifics layer on top (personal-angular-conventions for Angular). Assumes TypeScript 5+.
TypeScript strictness
strict: trueis the floor. Also enablenoUncheckedIndexedAccess,noImplicitOverride,noFallthroughCasesInSwitch,exactOptionalPropertyTypes, andnoImplicitReturns.- No
any. Useunknownfor genuinely unknown values and narrow with type guards. Ananythat must exist (untyped dependency) is isolated behind a typed wrapper, never spread through call sites. - No non-null assertions (
!.) without a comment explaining why the value cannot be null. Prefer narrowing or an early return. - No
@ts-ignore; use@ts-expect-errorwith a reason comment so it fails when the underlying issue is fixed. - Type guards return
value is T, notboolean. Centralize narrowing in named user-defined guards.
Type modeling
- Prefer discriminated unions (a literal
kind/typetag) over inheritance or optional-field soup for variant types. Exhaustive-check the tag in aswitchwith aneverdefault. - Use utility types (
Partial,Pick,Omit,Readonly,Record,ReturnType,Awaited) instead of redefining shapes. - String-literal unions over
enumfor closed sets that cross a runtime boundary (JSON, storage, wire).const enumonly when bundled in and never exposed across a package boundary. interfacefor object shapes meant to be implemented or extended;typefor unions, intersections, tuples, and mapped/conditional types. Pick one and stay consistent within a file.- Model "no value" deliberately: a single optional (
x?: T) overT | null | undefinedambiguity; don't mixnullandundefinedto mean the same thing (pick one per codebase -undefinedis the TS-idiomatic default). readonlyby default for data:readonlyproperties,ReadonlyArray<T>/readonly T[]for collections,as constfor literal config. Mutability is opt-in.