Skip to main content

typescript

TypeScript best practices for this monorepo. Use this skill when: (1) writing new TypeScript code, (2) reviewing TypeScript code, (3) working with API responses, fetch calls, or JSON parsing, (4) adding or modifying types and interfaces.

Informations de source

Dépôt
microsoft/scope
Dernière activité de la source
26 mai 2026 à 22:19
Langue détectée de SKILL.md
anglais
Étoiles
54
Forks
26

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
typescript
description
TypeScript best practices for this monorepo. Use this skill when: (1) writing new TypeScript code, (2) reviewing TypeScript code, (3) working with API responses, fetch calls, or JSON parsing, (4) adding or modifying types and interfaces.
metadata
{"version":"1.0.0"}
# TypeScript Best Practices ## Never Leave Values Untyped at `any` Boundaries Whenever data crosses a boundary that erases type information (`response.json()`, `JSON.parse()`, external library returns, database query results, queue message payloads), **immediately annotate or narrow the type**: ```typescript // ❌ BAD — `any` leaks through, wrong property access compiles silently const data = await response.json(); data.turns; // no error even if turns lives at data.run.turns const parsed = JSON.parse(rawMessage); parsed.requestId; // unverified assumption // ✅ GOOD — type boundary is explicit, TypeScript verifies all access import type { RequestDocument } from "shared"; const data: RequestDocument = await response.json(); data.run?.turns; // correct path, verified at compile time const parsed: QueueMessagePayload = JSON.parse(rawMessage); parsed.requestId; // known to exist ``` ### Why This Matters - `any` propagates silently — one untyped value infects everything it touches - Bugs from wrong property paths are invisible at compile time - Tests may share the same wrong assumption as the code (mocks mirror the bug) - Adding a type annotation is zero-cost at runtime but catches entire classes of bugs ### Guidelines 1. **Import the shared type** from `packages/shared` when one exists (e.g., `RequestDocument`, `RunState`, `ReportDocument`) 2. **Create a local interface** if no shared type exists and the response shape is known 3. **Use Zod `.parse()`** when you need runtime validation (e.g., external APIs you don't control) 4. **Use optional chaining** (`?.`) instead of `|| {}` fallbacks — it preserves type narrowing ## Prefer Optional Chaining Over Fallback Objects ```typescript // ❌ BAD — `|| {}` erases type information, downstream access is untyped const run = request.run || {}; run.turns; // type is `{}`, no autocomplete, no error checking // ✅ GOOD — preserves the original type, TypeScript tracks nullability const run = request.run; run?.turns; // type is `ConversationTurn[] | undefined` ``` ## Use Shared Types from `packages/shared` This monorepo defines canonical types in `packages/shared/src/types/`. Always import from there rather than redeclaring shapes: | Type | Use For | | --- | --- | | `RequestDocument` | Full request document (includes `run?: RunState`) | | `RunState` | Per-attempt run state (status, turns, outcome) | | `ConversationTurn` | Individual iteration within a run | | `ReportDocument` | Report job state | | `ReportTemplateDocument` | Report template configuration | | `LogEvent` | Structured log entry | | `Scenario` | Task + criteria definition | ## Avoid `any` in New Code - Use `unknown` when the type is genuinely not known, then narrow with type guards - Use generics when writing reusable utilities - If you must use `any` (e.g., third-party library boundaries), contain it — cast to a typed variable immediately ```typescript // ❌ BAD — any spreads and defeats type checking function process(data: any) { return data.items.map((i: any) => i.name); } // ✅ GOOD — typed boundary, any is contained interface ApiResponse { items: Array<{ name: string }> } function process(data: unknown): string[] { const typed = data as ApiResponse; return typed.items.map(i => i.name); } ```
Voir sur GitHub