Skip to main content

typescript-fieldguide

This skill should be used when writing TypeScript, eliminating any types, implementing Zod validation, or when strict type safety is needed. Covers modern TS 5.5+ features and runtime validation patterns.

معلومات المصدر

المستودع
outfitter-dev/outfitter
آخر نشاط في المصدر
٢٤ فبراير ٢٠٢٦ في ٢٣:٠٩
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٦
التفرعات
١

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
16 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
typescript-fieldguide
description
This skill should be used when writing TypeScript, eliminating any types, implementing Zod validation, or when strict type safety is needed. Covers modern TS 5.5+ features and runtime validation patterns.
metadata
{"version":"1.0.1"}
# TypeScript Development Type-safe code = compile-time errors = runtime confidence. <when_to_use> - Writing new TypeScript code - Eliminating `any` types - Using modern TypeScript 5.5+ features - Validating API inputs/outputs with Zod - Implementing Result types and discriminated unions - Creating branded types for domain concepts NOT for: runtime-only logic unrelated to types, non-TypeScript projects </when_to_use> <config> **tsconfig.json** strict settings: ```json { "compilerOptions": { "strict": true, "noUncheckedIndexedAccess": true, "exactOptionalPropertyTypes": true, "noImplicitOverride": true, "noPropertyAccessFromIndexSignature": true, "noFallthroughCasesInSwitch": true, "noImplicitReturns": true, "forceConsistentCasingInFileNames": true, "verbatimModuleSyntax": true, "isolatedModules": true, "skipLibCheck": false } } ``` **Version requirements**: TS 5.2+ (`using`), TS 5.4+ (`NoInfer`), TS 5.5+ (inferred predicates) </config> ## Core Patterns <eliminating_any> `any` defeats the type system. Use `unknown` + guards. ```typescript // ❌ NEVER function process(data: any) { return data.value; } // ✅ ALWAYS function process(data: unknown): string { if (!hasValue(data)) throw new TypeError("Invalid"); return data.value.toString(); } function hasValue(v: unknown): v is { value: unknown } { return typeof v === "object" && v !== null && "value" in v; } ``` Validate at boundaries: ```typescript async function fetchUser(id: string): Promise<User> { const data: unknown = await fetch(`/api/users/${id}`).then((r) => r.json()); return UserSchema.parse(data); } ``` </eliminating_any> <result_types> Exceptions hide errors from types. Result makes them explicit. ```typescript type Result<T, E = Error> = | { readonly ok: true; readonly value: T } | { readonly ok: false; readonly error: E }; type UserError = | { readonly type: "not-found"; readonly id: string } | { readonly type: "network"; readonly message: string }; async function getUser(id: string): Promise<Result<User, UserError>> { try { const response = await fetch(`/api/users/${id}`); if (response.status === 404) return { ok: false, error: { type: "not-found", id } }; if (!response.ok) return { ok: false, error: { type: "network", message: response.statusText }, }; return { ok: true, value: await response.json() }; } catch (e) { return { ok: false, error: { type: "network", message: String(e) } }; } } // Caller must handle const result = await getUser(id); if (!result.ok) { switch (result.error.type) { case "not-found": return showNotFound(result.error.id); case "network": return showError(result.error.message); } } return renderUser(result.value); ``` See [result-pattern.md](references/result-pattern.md) for utilities (`map`, `flatMap`, `combine`). </result_types> <discriminated_unions> Prevent illegal state combinations. ```typescript // ❌ Allows { status: 'loading', data: user, error: 'Failed' } type Request = { status: 'idle'|'loading'|'success'|'error'; data?: User; error?: string; }; // ✅ Only valid states type RequestState = | { readonly status: 'idle' } | { readonly status: 'loading' } | { readonly status: 'success'; readonly data: User } | { readonly status: 'error'; readonly error: string }; function render(state: RequestState): JSX.Element { switch (state.status) { case 'idle': return <div>Ready</div>; case 'loading': return <div>Loading...</div>; case 'success': return <div>{state.data.name}</div>; case 'error': return <div>Error: {state.error}</div>; default: return assertNever(state); } } function assertNever(value: never): never { throw new Error(`Unhandled: ${JSON.stringify(value)}`); } ``` </discriminated_unions> <branded_types> Prevent mixing incompatible primitives. ```typescript declare const __brand: unique symbol; type Brand<T, B extends string> = T & { readonly [__brand]: B }; type UserId = Brand<string, "UserId">; type ProductId = Brand<string, "ProductId">; function createUserId(value: string): UserId { if (!/^user-\d+$/.test(value)) throw new TypeError(`Invalid: ${value}`); return value as UserId; } const userId = createUserId("user-123"); // getUser(productId); // ❌ Type error getUser(userId); // ✅ Works ``` Security: ```typescript type SanitizedHtml = Brand<string, "SanitizedHtml">; function sanitize(raw: string): SanitizedHtml { return escapeHtml(raw) as SanitizedHtml; } function render(html: SanitizedHtml): void { element.innerHTML = html; // Type proves sanitization } ``` See [branded-types.md](references/branded-types.md) for advanced patterns. </branded_types> ## Modern TypeScript (5.2+) <resource_management> `using` for automatic cleanup (TS 5.2+): ```typescript class DatabaseConnection implements Disposable { [Symbol.dispose]() { this.close(); } } function query() { using conn = new DatabaseConnection(); return conn.query("SELECT * FROM users"); } // Automatically closed async function asyncWork() { await using resource = new AsyncResource(); } // Disposed with await ``` Use for: connections, file handles, locks, transactions. </resource_management> <satisfies_operator> Validate type without widening (TS 4.9+): ```typescript const config = { port: 3000, host: "localhost", } satisfies Record<string, string | number>; config.port; // number (not string | number) const routes = { home: "/", user: "/user/:id", } as const satisfies Record<string, string>; type HomeRoute = typeof routes.home; // '/' ``` </satisfies_operator> <const_type_parameters> Preserve literals through generics (TS 5.0+): ```typescript function makeTuple<const T extends readonly unknown[]>(...args: T): T { return args; } const result = makeTuple("a", "b", "c"); // ['a', 'b', 'c'] not string[] ``` </const_type_parameters> <inferred_predicates> TS 5.5+ auto-infers type predicates: ```typescript function isString(x: unknown) { return typeof x === "string"; } // Inferred: (x: unknown) => x is string const strings = values.filter(isString); // string[] ``` </inferred_predicates> <template_literals> Pattern matching at type level: ```typescript type Route = `/${string}`; type ApiRoute = `/api/v${number}/${string}`; type ExtractParams<T extends string> = T extends `${string}:${infer P}/${infer R}` ? P | ExtractParams<`/${R}`> : T extends `${string}:${infer P}` ? P : never; type Params = ExtractParams<"/user/:id/post/:postId">; // 'id' | 'postId' ``` See [modern-features.md](references/modern-features.md) for TS 5.5-5.8. </template_literals> ## Zod Validation Schema = runtime validation + TypeScript type. <zod_core> ```typescript import { z } from "zod"; const UserSchema = z.object({ id: z.string().uuid(), email: z.string().email(), name: z.string().min(1).max(100), }); type User = z.infer<typeof UserSchema>; // safeParse preferred const result = UserSchema.safeParse(data); if (!result.success) { console.error(result.error.issues); return; } const user = result.data; ``` </zod_core> <zod_patterns> **Discriminated unions** (preferred over z.union): ```typescript const ApiResponse = z.discriminatedUnion("type", [ z.object({ type: z.literal("success"), data: z.unknown() }), z.object({ type: z.literal("error"), code: z.string(), message: z.string() }), ]); ``` **Environment variables**: ```typescript const EnvSchema = z.object({ NODE_ENV: z .enum(["development", "production", "test"]) .default("development"), DATABASE_URL: z.string().url(), PORT: z.coerce.number().int().positive().default(3000), }); const env = EnvSchema.parse(process.env); ``` **API validation (Hono)**: ```typescript import { zValidator } from "@hono/zod-validator"; app.post("/users", zValidator("json", UserSchema), (c) => { const user = c.req.valid("json"); return c.json(user); }); ``` See: - [zod-building-blocks.md](references/zod-building-blocks.md) - primitives, refinements, transforms - [zod-schemas.md](references/zod-schemas.md) - composition patterns - [zod-integration.md](references/zod-integration.md) - API/form/env integration </zod_patterns> ## Type Guards ```typescript // User-defined function isString(v: unknown): v is string { return typeof v === "string"; } // Assertion function assertString(v: unknown): asserts v is string { if (typeof v !== "string") throw new TypeError("Expected string"); } // With noUncheckedIndexedAccess const users: User[] = getUsers(); const first = users[0]; // User | undefined if (first !== undefined) processUser(first); ``` See [advanced-types.md](references/advanced-types.md) for utilities. ## TSDoc Types show structure. TSDoc shows intent. Critical for AI agents. ```typescript /** * Authenticates user and returns session token. * @param credentials - User login credentials * @returns Session token valid for 24 hours * @throws {AuthenticationError} Invalid credentials * @example * const token = await authenticate({ email, password }); */ export async function authenticate( credentials: Credentials ): Promise<SessionToken>; ``` Document: all exports, parameters with constraints, thrown errors, non-obvious returns. See [tsdoc-patterns.md](references/tsdoc-patterns.md) for comprehensive guide. <rules> ALWAYS: - Strict TypeScript config enabled - Type-only imports: `import type { User } from './types'` - Const assertions for literal types - Exhaustive matching with `assertNever` - Runtime validation at boundaries (Zod) - Branded types for domain/sensitive data - Result types for error-prone operations - `satisfies` for literal inference - `using` for resources with cleanup - TSDoc on all exports
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub