Claude
Skills
Sign in
Back

typescript-v6

Included with Lifetime
$97 forever

TypeScript 6+ guidance for project development, tsconfig configuration, diagnostics, module resolution, deprecations, and modern standard-library typings. Use when building or maintaining TypeScript 6+ projects, debugging compiler behavior, or working through TS 6-specific defaults and tooling such as `#/` subpath imports, `ignoreDeprecations`, `RegExp.escape`, `Temporal`, and `--stableTypeOrdering`. Triggers on typescript 6, ts 6, stableTypeOrdering, ignoreDeprecations, types array, noUncheckedSideEffectImports, baseUrl deprecated, moduleResolution node deprecated, and subpath imports.

Backend & APIs

What this skill does


# TypeScript 6 Skill

> Build, configure, and debug TypeScript 6+ projects with precise compiler guidance and modern module/runtime patterns.

## Before You Start

**This skill is for real TypeScript 6+ project work: daily development, configuration, debugging, and upgrades.**

| Metric | Without Skill | With Skill |
|--------|--------------|------------|
| Upgrade Investigation Time | ~90 min | ~30 min |
| Common tsconfig Regressions | 5+ | 0-1 |
| Token Usage | High (manual diffing) | Low (release-note-grounded guidance) |

### Known Issues This Skill Prevents

1. Surprise build failures from missing `types` entries after upgrading
2. Unexpected `dist/src/...` output because `rootDir` was never explicit
3. Deprecated `moduleResolution node` or `baseUrl` settings surviving into a TS 6 migration
4. Confusion about when to use `bundler` vs `nodenext`
5. Overusing `ignoreDeprecations: "6.0"` as a long-term fix instead of a temporary migration aid
6. Misunderstanding `--stableTypeOrdering` as a production performance flag instead of a TS 6→7 comparison tool
7. Missing Node/test globals because TS 6+ projects often need explicit `types` entries
8. New side-effect import errors because TS 6 applies stricter side-effect import checking

## Quick Start

### Step 1: Make the important options explicit

```json
{
  "compilerOptions": {
    "rootDir": "./src",
    "outDir": "./dist",
    "types": ["node"],
    "strict": true
  },
  "include": ["src/**/*"]
}
```

**Why this matters:** TypeScript 6 changed enough defaults and behaviors that explicit configuration now matters more in everyday work. `rootDir` and `types` are two of the most important settings to keep intentional.

### Step 2: Pick module resolution deliberately

```json
{
  "compilerOptions": {
    "module": "esnext",
    "moduleResolution": "bundler"
  }
}
```

**Why this matters:** TypeScript 6 deprecates `moduleResolution: "node"`/`"node10"`. Bundled apps should usually choose `bundler`, while Node.js packages should usually choose `nodenext`.

### Step 3: Use TS 6-era library typings only when the target/lib/runtime really supports them

```ts
const escaped = RegExp.escape('(hello)');

const value = new Map<string, number>().getOrInsert('count', 0);

const tomorrow = Temporal.Now.instant().add({ hours: 24 });
```

**Why this matters:** TypeScript 6 can type new platform APIs before every runtime ships them. Distinguish **compiler types available** from **runtime support available**.

### Step 4: Verify config and resolution before changing code

```bash
npx tsc --noEmit
npx tsc --showConfig
npx tsc --explainFiles
```

**Why this matters:** TS 6+ projects often fail because the effective config or included file graph is not what the project expects. Validate that first, then refactor.

## Critical Rules

### Always Do

- Make `rootDir` explicit when your sources are nested below the `tsconfig.json`
- Make the `types` array explicit for Node, test runners, Workers, Bun, or other global type providers when the project relies on those ambient globals
- Prefer `moduleResolution: "bundler"` for bundled web apps and `moduleResolution: "nodenext"` for modern Node.js packages
- Treat `ignoreDeprecations: "6.0"` as a short-term migration escape hatch, not the destination
- Use `paths` directly instead of relying on deprecated `baseUrl`
- Make `types` explicit when the project truly depends on Node, test, Worker, or Bun globals
- Treat side-effect imports as intentionally checked and fix their paths deliberately
- Verify runtime support before recommending `Temporal`, `getOrInsert`, or `RegExp.escape`
- Use `--stableTypeOrdering` only when comparing TS 6 and TS 7 behavior or investigating ordering-sensitive issues
- Use `satisfies`, exhaustive `never` checks, and assertion functions when TS 6+ code exposes type ambiguity that should be made explicit
- Re-run `tsc --noEmit` after config changes and again after type-pattern refactors

### Never Do

- Never recommend deprecated `moduleResolution: "node"` / `"node10"` as the forward-looking path
- Never recommend removed `moduleResolution: "classic"` as a fallback path
- Never leave `types` implicit if a project depends on `@types/node`, test globals, or platform globals
- Never assume `ignoreDeprecations: "6.0"` will keep working in TypeScript 7
- Never present TS 7 preview context as if it were already the default compiler runtime
- Never imply that TypeScript types guarantee runtime availability for new ECMAScript APIs
- Never import pre-TS 6 tsconfig advice that still uses `skipDefaultLibCheck`, `downlevelIteration`, or old AMD/UMD/SystemJS examples

### Common Mistakes

**Wrong - relying on pre-TS 6 ambient type loading:**
```json
{
  "compilerOptions": {
    "outDir": "./dist"
  }
}
```

**Correct - declare what global types the project actually needs:**
```json
{
  "compilerOptions": {
    "outDir": "./dist",
    "types": ["node"]
  }
}
```

**Why:** In TS 6+, explicit `types` improves performance and predictability when the project depends on ambient globals.

**Wrong - keep deprecated path alias setup unchanged:**
```json
{
  "compilerOptions": {
    "baseUrl": "./src",
    "paths": {
      "@app/*": ["app/*"]
    }
  }
}
```

**Correct - inline the source prefix in `paths`:**
```json
{
  "compilerOptions": {
    "paths": {
      "@app/*": ["./src/app/*"]
    }
  }
}
```

**Why:** `baseUrl` is deprecated in TS 6. The forward-looking setup is direct `paths` entries.

**Wrong - type widening hides the real config contract:**
```ts
const compilerMode = {
  moduleResolution: 'bundler',
  strict: true,
};
```

**Correct - keep literals checked without widening:**
```ts
const compilerMode = {
  moduleResolution: 'bundler',
  strict: true,
} satisfies {
  moduleResolution: 'bundler' | 'nodenext';
  strict: boolean;
};
```

**Why:** `satisfies` is not new in TS 6, but it is one of the cleanest ways to make config and option objects precise without losing inference.

**Wrong - union handling silently misses a new case:**
```ts
type ResolutionMode = 'bundler' | 'nodenext' | 'preserve';

function describeMode(mode: ResolutionMode) {
  if (mode === 'bundler') return 'bundled app';
  return 'node-style runtime';
}
```

**Correct - exhaustive union handling:**
```ts
type ResolutionMode = 'bundler' | 'nodenext' | 'preserve';

function describeMode(mode: ResolutionMode) {
  switch (mode) {
    case 'bundler':
      return 'bundled app';
    case 'nodenext':
      return 'node-style runtime';
    case 'preserve':
      return 'mixed emit strategy';
    default: {
      const exhaustive: never = mode;
      return exhaustive;
    }
  }
}
```

**Why:** TypeScript 6+ projects often rely on unions for config, platform, and runtime state. Exhaustive `never` checks make missing cases obvious.

**Wrong - use `stableTypeOrdering` as a normal build flag:**
```bash
tsc --stableTypeOrdering --build
```

**Correct - use it only for comparison/debugging:**
```bash
tsc --noEmit --stableTypeOrdering
```

**Why:** The flag exists to reduce TS 6 vs TS 7 output noise. It can meaningfully slow type-checking and is not intended as a permanent default.

## Known Issues Prevention

| Issue | Root Cause | Solution |
|-------|-----------|----------|
| `process` / `describe` / `fs` suddenly missing | The project relied on ambient type discovery that is no longer safe to assume during TS 6 migration work | Add explicit entries like `"types": ["node", "jest"]` |
| Output moves to `dist/src/...` | The project relied on inferred source-root behavior that TS 6 migration work often needs to replace with explicit config | Set `rootDir` explicitly, usually `./src` |
| Upgrade warnings explode | Deprecated module resolution or emit-era options survived from older configs | Migrate to `bundler` or `nodenext`; remove deprecated options |
| Side-effect imports suddenly error | Side-effect import checking is stricter in TS 6+ projects | Fix typos, add explicit files, or tighten import paths intention

Related in Backend & APIs