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.

来源信息

仓库
microsoft/scope
最近来源活动
2026年5月26日 22:19
检测到的 SKILL.md 语言
英语
星标
54
Forks
26

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
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); } ```
在 GitHub 查看