SuperAPI AI Directory

ts-language-patterns

Agents & models

View repository

Updated 10-15 21:49

About this skill

It also covers fixing LLM-authored anti-patterns: legacy enum (un-erasable by Node's type stripper, replace with const objects as const), namespace wrapping runtime code, and missing import type under verbatimModuleSyntax.

Out of scope: tsconfig/compiler flags belong to ts-config; SOLID structure and file-size rules belong to solid-generic; framework-specific APIs are not covered.

TypeScript Language Patterns (TS 7.0)

Agent Workflow (MANDATORY)

Before writing non-trivial TypeScript, spawn 3 agents in parallel, one Agent call each with a name:

  1. fuse-ai-pilot:explore-codebase - Detect existing idioms, verbatimModuleSyntax, tsconfig
  2. fuse-ai-pilot:research-expert - Verify current syntax on typescriptlang.org
  3. mcp__context7__query-docs - /microsoft/typescript for exact API shapes

After writing, run fuse-ai-pilot:sniper for validation.


Overview

Feature What it gives you
const type parameters <const T> infers the narrowest literal type without as const at call sites
using / await using Deterministic cleanup via Symbol.dispose / Symbol.asyncDispose
Standard decorators ECMAScript decorators — NOT experimentalDecorators
satisfies Validate a value against a type while keeping its narrow inferred type
6.0 inference Method-syntax callbacks are no longer contextually sensitive → order-independent inference
7.0 template literals Inference splits on Unicode code points, not UTF-16 surrogate halves

Critical Rules

  1. import type is mandatory under verbatimModuleSyntax - type-only imports must say type, or emit/stripping breaks.
  2. No legacy enum - prefer const objects as const; enum is un-erasable by Node's type stripper.
  3. No namespace with runtime code - use ESM modules; type-only namespace is acceptable.
  4. Use standard decorators - never enable experimentalDecorators for new code.
  5. Never rely on implicit any - strict is the default since 6.0 (kept in 7.0); annotate or infer explicitly.

Reference Guide

Concepts

Topic Reference When to Consult
Resource management resource-management.md Load when using using / await using / disposables
Generics & inference generics-and-inference.md Load when using const type params, satisfies, or debugging inference
Decorators decorators.md Load when adding decorators
LLM pitfalls llm-pitfalls.md Load when reviewing or migrating legacy/AI-authored TypeScript

Templates

Template When to Use
modern-patterns.md Copy-paste const/satisfies/decorator examples
resource-management.md Copy-paste using / DisposableStack examples

Quick Reference

const type parameter

function first<const T extends readonly unknown[]>(arr: T): T[0] {
  return arr[0];
}
const x = first(["a", "b"]); // x: "a"  (literal, no `as const` needed)

using for deterministic cleanup

function openFile(path: string) {
  const handle = acquire(path);
  return { handle, [Symbol.dispose]() { release(handle); } };
}
{
  using file = openFile("./data"); // released automatically at block end
}

satisfies

const config = {
  port: 3000,
  host: "localhost",
} satisfies Record<string, string | number>;
// config.port stays `number`, not widened to `string | number`

Best Practices

DO

  • Replace enum Color { Red } with const Color = { Red: "red" } as const
  • Reach for using over manual try/finally cleanup when a resource has a disposer
  • Use satisfies instead of a type annotation when you want to keep the narrow inferred type

DON'T

  • Write import { SomeType } for a type-only import — use import type { SomeType }
  • Enable experimentalDecorators or emitDecoratorMetadata for new code
  • Use namespace to organize runtime code — that is what ESM modules are for