typescript-pro
Strict TypeScript with zero-any tolerance, no-unsafe-* lints, floating-promise prevention, and disciplined type-system usage. Use when implementing, debugging, refactoring, or reviewing TypeScript code; resolving type errors; configuring tsconfig/ESLint/Prettier; setting up React/Next/Express patterns; eliminating any/unknown drift; or evaluating advanced generics, conditional types, and inference. Applies to any TypeScript work unless a more specific role overrides.
What this skill does
# TypeScript Pro
Senior-level TypeScript expertise for production projects. Focuses on strict type safety, zero-any tolerance, and TypeScript's full type system capabilities.
## When Invoked
1. Review `tsconfig.json` and `eslint.config.js` for project conventions
2. For build system setup, invoke the **just-pro** skill (covers just vs make)
3. Apply type-first development and established project patterns
## Core Standards
**Required:**
- Strict mode enabled with all compiler flags
- **NO explicit or implicit `any`** - use `unknown` and narrow
- **NO type assertions to circumvent the type system** (`as any`, `as unknown as T`)
- **NO dangling promises** - await, return, or void explicitly
- All exported functions have explicit return types
- ESLint strict-type-checked passes with project configuration
- Table-driven tests for multiple cases
**Foundational Principles:**
- **Single Responsibility**: One module = one purpose, one function = one job
- **No God Objects**: Split large classes/objects; if it has 10+ methods or properties, decompose
- **Dependency Injection**: Pass dependencies via constructor/params, don't instantiate internally
- **Small Interfaces**: Prefer many small types over few large ones; compose with intersection types
- **Composition over Inheritance**: Use object composition and mixins, not deep class hierarchies
---
## Project Setup (TypeScript 5.5+)
### Version Management
Pin Node version with [mise](https://mise.jdx.dev): `mise use node@22` (creates `.mise.toml` — commit it). Team members run `mise install`. See **mise** skill for setup.
### New Project Quick Start
```bash
# Initialize
npm init -y
npm install -D typescript typescript-eslint @eslint-community/eslint-plugin-eslint-comments eslint-plugin-sonarjs prettier lint-staged vitest
# Add scripts to package.json:
npm pkg set scripts.typecheck="tsc --noEmit"
npm pkg set scripts.lint="eslint src/"
npm pkg set scripts.test="vitest run"
npm pkg set scripts.check="npm run typecheck && npm run lint && npm run test"
# Configure lint-staged (formats only staged files on commit)
npm pkg set lint-staged --json '{"*.{ts,tsx}": ["prettier --write"], "*.{json,yml,yaml}": ["prettier --write"]}'
# Create .prettierignore (prevent formatting machine-generated and non-TS files)
cat > .prettierignore << 'EOF'
# ============================================================================
# DO NOT ADD SOURCE FILES HERE TO WORK AROUND LINE LENGTH LIMITS.
#
# If prettier expansion pushes a file past max-lines (400) or
# max-lines-per-function (60), the file needs to be DECOMPOSED — extract
# functions, split into modules, rearchitect. That is the engineering fix.
#
# Adding source files here suppresses formatting without fixing the real
# problem. The line limits are design signals, not obstacles to route around.
# ============================================================================
# Machine-generated / non-source (safe to exclude)
coverage/
dist/
node_modules/
.worktrees/
.timbers/
.beads/
EOF
# Verify
npm run check
```
### Pre-commit Hook
Quality gates run via a git pre-commit hook. With beads 1.0+, hooks live in **`.beads/hooks/`** (committed to git, managed by `bd hooks install --beads`). Beads, timbers, and your quality gates all coexist in the same hook file via section markers — content outside markers is preserved across reinstalls.
**Setup:**
1. `bd init` (creates `.beads/hooks/` and sets `core.hooksPath = .beads/hooks`)
2. `timbers hooks install` (detects `core.hooksPath`, appends into existing files alongside beads)
3. Add quality gates between the BEADS and TIMBERS marker sections — they're preserved across `bd hooks install --force` and `timbers hooks install` reruns
**Pre-commit hook structure** (`.beads/hooks/pre-commit`):
```bash
#!/usr/bin/env sh
# --- BEGIN BEADS INTEGRATION v1.0.x --- (managed — do not edit)
# ... bd hooks run pre-commit shim ...
# --- END BEADS INTEGRATION v1.0.x ---
# Quality gates (preserved across reinstalls — outside markers)
if [ -f .git/MERGE_HEAD ]; then
echo "Merge commit — skipping lint-staged"
else
npx lint-staged
fi
if command -v just >/dev/null 2>&1 && [ -f justfile ]; then
just check
else
npm run check
fi
# --- timbers section (managed by timbers hooks install)
# ... timbers hook run pre-commit shim ...
# --- end timbers section ---
```
**Why this order:** Beads runs first (fast: bd's internal hook handles auto-export+stage of `.beads/issues.jsonl`). Quality gates run next (slowest, may fail — but `bd export` already happened, so beads state is captured even if gates fail and the commit aborts). Timbers runs last (post-gate, post-export).
**Auto-export defaults (beads 1.0+):**
- `export.auto = true` — every `bd` mutation writes `.beads/issues.jsonl` (60s throttled)
- `export.git-add = true` — auto-stages it
- The pre-commit hook forces a flush, so commits always carry current state
**Justfile recipe:**
```just
hooks:
@bd hooks install --force --beads >/dev/null && echo " ✅ beads hooks installed"
@if command -v timbers >/dev/null 2>&1; then \
timbers hooks install >/dev/null && echo " ✅ timbers hooks installed"; \
fi
@current=$(git config --get core.hooksPath 2>/dev/null || true); \
if [ "$current" != ".beads/hooks" ]; then \
git config core.hooksPath .beads/hooks; \
echo " ✅ core.hooksPath fixed to .beads/hooks (was $current)"; \
fi
```
**Note on `core.hooksPath`:** `bd hooks install --force` may set this to an absolute path. Force it relative — worktrees share repo config, and an absolute path won't resolve from a worktree's working dir.
**New dev/agent onboarding:** `git clone <repo> && just setup` (which includes `just hooks`).
If a project currently uses husky, migrate:
```bash
npm uninstall husky && rm -rf .husky && npm pkg delete scripts.prepare
bd hooks install --force --beads
git config core.hooksPath .beads/hooks
# Move any custom hook content into .beads/hooks/<hook> outside the BEADS markers
```
### Monorepo Variant
In monorepos (multiple packages, possibly mixed languages), adjust the setup:
**lint-staged: scoped to TS packages only.** Don't format Go/Rust code with Prettier — they have their own formatters (goimports, rustfmt).
```bash
# Root package.json (npm workspaces / turborepo):
npm pkg set lint-staged --json '{"packages/web/**/*.{ts,tsx}": ["prettier --write"], "*.{json,yml,yaml}": ["prettier --write"]}'
# Or independent packages (no workspaces): install lint-staged per TS package
```
**Pre-commit: lint-staged only, no `npm run check`.** Full quality gates across all packages are too slow for pre-commit. Run lint-staged in the hook, run full gates via `just check` or CI.
```bash
# .beads/hooks/pre-commit (between BEADS markers and timbers section):
npx lint-staged
```
(beads 1.0+ auto-exports + auto-stages `.beads/issues.jsonl` on every mutation; the manual export+stage lines older docs showed are no longer needed.)
For mixed-language monorepos without workspaces, detect which packages have staged files:
```bash
if git diff --cached --name-only | grep -q '^packages/web/'; then
(cd packages/web && npx lint-staged)
fi
```
**`.prettierrc`: root-level.** Prettier walks up the directory tree, so a single root config covers all TS packages. Use per-package configs only if packages need different formatting.
**Required Config Files:** Copy `references/gitignore` → `.gitignore`, `references/prettierrc.json` → `.prettierrc`, then create `tsconfig.json` and `eslint.config.js` per the templates below.
### Developer Onboarding
```bash
git clone <repo> && cd <repo>
just setup # Runs mise trust/install + npm ci
just check # Verify everything works
```
Or manually:
```bash
mise trust && mise install # Get pinned Node version
npm ci # Get dependencies
```
**Why strict configs?** Type errors caught at compile time are 10x cheaper than runtime bugs. Strict linting prevents `any` Related in Web Dev
generating-lwc-components
IncludedLightning Web Components with PICKLES methodology and 165-point scoring. Use this skill when the user creates or edits LWC components, builds wire service patterns, or writes Jest tests for LWC. TRIGGER when: user creates/edits LWC components, touches lwc/**/*.js, .html, .css, .js-meta.xml files, or asks about wire service, SLDS, or Jest LWC tests. DO NOT TRIGGER when: Apex classes (use generating-apex), Aura components, or Visualforce.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Set up queries with useQuery, mutations with useMutation, configure QueryClient caching strategies, implement optimistic updates, and handle infinite scroll with useInfiniteQuery. Use when: setting up data fetching in React projects, migrating from v4 to v5, or fixing object syntax required errors, query callbacks removed issues, cacheTime renamed to gcTime, isPending vs isLoading confusion, keepPreviousData removed problems.
document-processor-api
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
nutrient-document-processing
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Covers useMutationState, simplified optimistic updates, throwOnError, network mode (offline/PWA), and infiniteQueryOptions. Use when setting up data fetching, fixing v4→v5 migration errors (object syntax, gcTime, isPending, keepPreviousData), or debugging SSR/hydration issues with streaming server components.
accelint-nextjs-best-practices
IncludedNext.js performance optimization and best practices. Use when writing Next.js code (App Router or Pages Router); implementing Server Components, Server Actions, or API routes; optimizing RSC serialization, data fetching, or server-side rendering; reviewing Next.js code for performance issues; fixing authentication in Server Actions; or implementing Suspense boundaries, parallel data fetching, or request deduplication.