Comprehensive TypeScript refactoring and modernization guide designed for AI agents and LLMs. Contains 43 rules across 8 categories, prioritized by impact to guide automated refactoring, code review, and code generation.
When to Apply
Reference these guidelines when:
Refactoring TypeScript code for type safety and maintainability
Designing type architectures (discriminated unions, branded types, generics)
Narrowing types to eliminate unsafe as casts
Adopting modern TypeScript 4.x-5.x features (satisfies, using, const type parameters)
Optimizing compiler performance in large codebases
Implementing type-safe error handling patterns
Reviewing code for TypeScript quirks and pitfalls
Rule Categories by Priority
Priority
Category
Impact
Prefix
1
Type Architecture
CRITICAL
arch-
2
Type Narrowing & Guards
CRITICAL
narrow-
3
Modern TypeScript
HIGH
modern-
4
Generic Patterns
HIGH
generic-
5
Compiler Performance
MEDIUM-HIGH
compile-
6
Error Safety
MEDIUM
error-
7
Runtime Patterns
MEDIUM
perf-
8
Quirks & Pitfalls
LOW-MEDIUM
quirk-
Quick Reference
1. Type Architecture (CRITICAL)
arch-discriminated-unions — Use discriminated unions over string enums for exhaustive pattern matching
arch-branded-types — Use branded types for domain identifiers to prevent value mix-ups
arch-satisfies-over-annotation — Use satisfies for config objects to preserve literal types
arch-interfaces-over-intersections — Extend interfaces instead of intersecting types for better error messages
arch-const-assertion — Use as const for immutable literal inference
arch-readonly-by-default — Default to readonly types for function parameters and return values
arch-avoid-partial-abuse — Avoid Partial<T> abuse for builder patterns
2. Type Narrowing & Guards (CRITICAL)
narrow-custom-type-guards — Write custom type guards instead of type assertions
narrow-assertion-functions — Use assertion functions for precondition checks
narrow-exhaustive-switch — Enforce exhaustive switch with never
narrow-in-operator — Narrow with the in operator for interface unions
narrow-eliminate-as-casts — Eliminate as casts with proper narrowing chains
narrow-typeof-chains — Use typeof narrowing before property access
3. Modern TypeScript (HIGH)
modern-using-keyword — Use the using keyword for resource cleanup
modern-const-type-parameters — Use const type parameters for literal inference
modern-template-literal-types — Use template literal types for string patterns
modern-noinfer-utility — Use NoInfer to control type parameter inference
modern-accessor-keyword — Use accessor for auto-generated getters and setters
modern-verbatim-module-syntax — Enable verbatimModuleSyntax for explicit import types
4. Generic Patterns (HIGH)
generic-infer-over-annotate — Let TypeScript infer instead of explicit annotation
generic-avoid-distributive-surprises — Control distributive conditional types
generic-mapped-type-utilities — Build custom mapped types for repeated transformations
generic-return-type-inference — Preserve return type inference in generic functions
5. Compiler Performance (MEDIUM-HIGH)
compile-explicit-return-types — Add explicit return types to exported functions
compile-avoid-deep-recursion — Avoid deeply recursive type definitions
compile-project-references — Use project references for monorepo builds
compile-base-types-over-unions — Use base types instead of large union types
6. Error Safety (MEDIUM)
error-result-type — Use Result types instead of thrown exceptions
error-exhaustive-error-handling — Use exhaustive checks for typed error variants
error-typed-catch — Type catch clause variables as unknown
error-never-for-unreachable — Use never to mark unreachable code paths
error-discriminated-error-unions — Model domain errors as discriminated unions
7. Runtime Patterns (MEDIUM)
perf-union-literals-over-enums — Use union literals instead of enums
perf-avoid-delete-operator — Avoid the delete operator on objects
perf-object-freeze-const — Use Object.freeze with as const for true immutability
perf-object-keys-narrowing — Avoid Object.keys type widening
perf-map-set-over-object — Use Map and Set over plain objects for dynamic collections
8. Quirks & Pitfalls (LOW-MEDIUM)
quirk-excess-property-checks — Understand excess property checks on object literals
quirk-empty-object-type — Avoid the {} type — it means non-nullish
quirk-type-widening-let — Prevent type widening with let declarations
quirk-variance-annotations — Use variance annotations for generic interfaces
quirk-structural-typing-escapes — Guard against structural typing escape hatches
How to Use
Read individual reference files for detailed explanations and code examples:
Section definitions — Category structure and impact levels
Rule template — Template for adding new rules
Reference Files
File
Description
references/_sections.md
Category definitions and ordering
assets/templates/_template.md
Template for new rules
metadata.json
Version and reference information
1---2name: typescript-refactor3description: TypeScript Refactor Best Practices4---5# TypeScript Refactor Best Practices67Comprehensive TypeScript refactoring and modernization guide designed for AI agents and LLMs. Contains 43 rules across 8 categories, prioritized by impact to guide automated refactoring, code review, and code generation.89## When to Apply1011Reference these guidelines when:12- Refactoring TypeScript code for type safety and maintainability13- Designing type architectures (discriminated unions, branded types, generics)14- Narrowing types to eliminate unsafe `as` casts15- Adopting modern TypeScript 4.x-5.x features (`satisfies`, `using`, const type parameters)16- Optimizing compiler performance in large codebases17- Implementing type-safe error handling patterns18- Reviewing code for TypeScript quirks and pitfalls1920## Rule Categories by Priority2122| Priority | Category | Impact | Prefix |23|----------|----------|--------|--------|24| 1 | Type Architecture | CRITICAL | `arch-` |25| 2 | Type Narrowing & Guards | CRITICAL | `narrow-` |26| 3 | Modern TypeScript | HIGH | `modern-` |27| 4 | Generic Patterns | HIGH | `generic-` |28| 5 | Compiler Performance | MEDIUM-HIGH | `compile-` |29| 6 | Error Safety | MEDIUM | `error-` |30| 7 | Runtime Patterns | MEDIUM | `perf-` |31| 8 | Quirks & Pitfalls | LOW-MEDIUM | `quirk-` |3233## Quick Reference3435### 1. Type Architecture (CRITICAL)3637- [`arch-discriminated-unions`](references/arch-discriminated-unions.md) — Use discriminated unions over string enums for exhaustive pattern matching38- [`arch-branded-types`](references/arch-branded-types.md) — Use branded types for domain identifiers to prevent value mix-ups39- [`arch-satisfies-over-annotation`](references/arch-satisfies-over-annotation.md) — Use `satisfies` for config objects to preserve literal types40- [`arch-interfaces-over-intersections`](references/arch-interfaces-over-intersections.md) — Extend interfaces instead of intersecting types for better error messages41- [`arch-const-assertion`](references/arch-const-assertion.md) — Use `as const` for immutable literal inference42- [`arch-readonly-by-default`](references/arch-readonly-by-default.md) — Default to readonly types for function parameters and return values43- [`arch-avoid-partial-abuse`](references/arch-avoid-partial-abuse.md) — Avoid `Partial<T>` abuse for builder patterns4445### 2. Type Narrowing & Guards (CRITICAL)4647- [`narrow-custom-type-guards`](references/narrow-custom-type-guards.md) — Write custom type guards instead of type assertions48- [`narrow-assertion-functions`](references/narrow-assertion-functions.md) — Use assertion functions for precondition checks49- [`narrow-exhaustive-switch`](references/narrow-exhaustive-switch.md) — Enforce exhaustive switch with `never`50- [`narrow-in-operator`](references/narrow-in-operator.md) — Narrow with the `in` operator for interface unions51- [`narrow-eliminate-as-casts`](references/narrow-eliminate-as-casts.md) — Eliminate `as` casts with proper narrowing chains52- [`narrow-typeof-chains`](references/narrow-typeof-chains.md) — Use `typeof` narrowing before property access5354### 3. Modern TypeScript (HIGH)5556- [`modern-using-keyword`](references/modern-using-keyword.md) — Use the `using` keyword for resource cleanup57- [`modern-const-type-parameters`](references/modern-const-type-parameters.md) — Use const type parameters for literal inference58- [`modern-template-literal-types`](references/modern-template-literal-types.md) — Use template literal types for string patterns59- [`modern-noinfer-utility`](references/modern-noinfer-utility.md) — Use `NoInfer` to control type parameter inference60- [`modern-accessor-keyword`](references/modern-accessor-keyword.md) — Use `accessor` for auto-generated getters and setters61- [`modern-verbatim-module-syntax`](references/modern-verbatim-module-syntax.md) — Enable `verbatimModuleSyntax` for explicit import types6263### 4. Generic Patterns (HIGH)6465- [`generic-infer-over-annotate`](references/generic-infer-over-annotate.md) — Let TypeScript infer instead of explicit annotation66- [`generic-constrain-dont-overconstrain`](references/generic-constrain-dont-overconstrain.md) — Constrain generics minimally67- [`generic-avoid-distributive-surprises`](references/generic-avoid-distributive-surprises.md) — Control distributive conditional types68- [`generic-mapped-type-utilities`](references/generic-mapped-type-utilities.md) — Build custom mapped types for repeated transformations69- [`generic-return-type-inference`](references/generic-return-type-inference.md) — Preserve return type inference in generic functions7071### 5. Compiler Performance (MEDIUM-HIGH)7273- [`compile-explicit-return-types`](references/compile-explicit-return-types.md) — Add explicit return types to exported functions74- [`compile-avoid-deep-recursion`](references/compile-avoid-deep-recursion.md) — Avoid deeply recursive type definitions75- [`compile-project-references`](references/compile-project-references.md) — Use project references for monorepo builds76- [`compile-base-types-over-unions`](references/compile-base-types-over-unions.md) — Use base types instead of large union types7778### 6. Error Safety (MEDIUM)7980- [`error-result-type`](references/error-result-type.md) — Use Result types instead of thrown exceptions81- [`error-exhaustive-error-handling`](references/error-exhaustive-error-handling.md) — Use exhaustive checks for typed error variants82- [`error-typed-catch`](references/error-typed-catch.md) — Type catch clause variables as `unknown`83- [`error-never-for-unreachable`](references/error-never-for-unreachable.md) — Use `never` to mark unreachable code paths84- [`error-discriminated-error-unions`](references/error-discriminated-error-unions.md) — Model domain errors as discriminated unions8586### 7. Runtime Patterns (MEDIUM)8788- [`perf-union-literals-over-enums`](references/perf-union-literals-over-enums.md) — Use union literals instead of enums89- [`perf-avoid-delete-operator`](references/perf-avoid-delete-operator.md) — Avoid the `delete` operator on objects90- [`perf-object-freeze-const`](references/perf-object-freeze-const.md) — Use `Object.freeze` with `as const` for true immutability91- [`perf-object-keys-narrowing`](references/perf-object-keys-narrowing.md) — Avoid `Object.keys` type widening92- [`perf-map-set-over-object`](references/perf-map-set-over-object.md) — Use `Map` and `Set` over plain objects for dynamic collections9394### 8. Quirks & Pitfalls (LOW-MEDIUM)9596- [`quirk-excess-property-checks`](references/quirk-excess-property-checks.md) — Understand excess property checks on object literals97- [`quirk-empty-object-type`](references/quirk-empty-object-type.md) — Avoid the `{}` type — it means non-nullish98- [`quirk-type-widening-let`](references/quirk-type-widening-let.md) — Prevent type widening with `let` declarations99- [`quirk-variance-annotations`](references/quirk-variance-annotations.md) — Use variance annotations for generic interfaces100- [`quirk-structural-typing-escapes`](references/quirk-structural-typing-escapes.md) — Guard against structural typing escape hatches101102## How to Use103104Read individual reference files for detailed explanations and code examples:105106- [Section definitions](references/_sections.md) — Category structure and impact levels107- [Rule template](assets/templates/_template.md) — Template for adding new rules108109## Reference Files110111| File | Description |112|------|-------------|113| [references/_sections.md](references/_sections.md) | Category definitions and ordering |114| [assets/templates/_template.md](assets/templates/_template.md) | Template for new rules |115| [metadata.json](metadata.json) | Version and reference information |
Run npx skillmds@latest add comeonoliver/typescript-refactor in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
TypeScript Refactor Best Practices It is listed under Coding & Dev Tools on SkillMD.
This skill has not completed SkillMD's automated safety review yet. Independent scanners report: SkillSpector: PASS, Skill Scanner: PASS. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
ComeOnOliver (@comeonoliver) published this skill. Their other Agent Skills are listed on their SkillMD profile.