Skip to main content

typescript-patterns

TypeScript types: generics, discriminated unions, Zod, satisfies, branded types. Triggers: TypeScript, TS, generics, Zod, satisfies, strict mode.

来源信息

仓库
softspark/ai-toolkit
最近来源活动
2026年5月6日 09:48
检测到的 SKILL.md 语言
英语
星标
179
分支
21

安装方式

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

检查来源文件

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

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
typescript-patterns
description
TypeScript types: generics, discriminated unions, Zod, satisfies, branded types. Triggers: TypeScript, TS, generics, Zod, satisfies, strict mode.
effort
medium
user-invocable
false
allowed-tools
Read
# TypeScript/JavaScript Patterns ## TypeScript Configuration ### Strict tsconfig.json ```json { "compilerOptions": { "strict": true, "noUncheckedIndexedAccess": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "exactOptionalPropertyTypes": true, "moduleResolution": "bundler", "module": "ESNext", "target": "ES2022", "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "resolveJsonModule": true, "isolatedModules": true, "declaration": true, "declarationMap": true, "sourceMap": true, "outDir": "./dist", "rootDir": "./src" }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] } ``` ## ESLint + Prettier ```json // .eslintrc.json (flat config recommended for new projects) { "extends": [ "eslint:recommended", "plugin:@typescript-eslint/recommended-type-checked", "prettier" ], "parser": "@typescript-eslint/parser", "parserOptions": { "project": "./tsconfig.json" }, "rules": { "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }], "@typescript-eslint/no-floating-promises": "error", "@typescript-eslint/no-misused-promises": "error" } } ``` ## React Patterns ### Functional Component ```tsx interface UserCardProps { user: User; onSelect?: (id: string) => void; } export function UserCard({ user, onSelect }: UserCardProps) { const handleClick = useCallback(() => { onSelect?.(user.id); }, [user.id, onSelect]); return ( <div onClick={handleClick} role="button" tabIndex={0}> <h3>{user.name}</h3> <p>{user.email}</p> </div> ); } ``` ### Custom Hook ```tsx function useAsync<T>(fn: () => Promise<T>, deps: unknown[]) { const [state, setState] = useState<{ data: T | null; error: Error | null; loading: boolean; }>({ data: null, error: null, loading: true }); useEffect(() => { let cancelled = false; setState(prev => ({ ...prev, loading: true })); fn() .then(data => { if (!cancelled) setState({ data, error: null, loading: false }); }) .catch(error => { if (!cancelled) setState({ data: null, error, loading: false }); }); return () => { cancelled = true; }; }, deps); return state; } ``` ### Context Pattern ```tsx interface AuthContextType { user: User | null; login: (credentials: Credentials) => Promise<void>; logout: () => void; } const AuthContext = createContext<AuthContextType | null>(null); export function useAuth() { const context = useContext(AuthContext); if (!context) throw new Error("useAuth must be within AuthProvider"); return context; } ``` ## Next.js App Router ### Server Component (default) ```tsx // app/users/page.tsx export default async function UsersPage() { const users = await db.user.findMany(); return <UserList users={users} />; } ``` ### Server Action ```tsx "use server"; import { revalidatePath } from "next/cache"; export async function createUser(formData: FormData) { const name = formData.get("name") as string; await db.user.create({ data: { name } }); revalidatePath("/users"); } ``` ## Node.js/Express Patterns ### Type-safe Route Handler ```typescript import { Router, Request, Response } from "express"; import { z } from "zod"; const CreateUserSchema = z.object({ name: z.string().min(1).max(100), email: z.string().email(), }); router.post("/users", async (req: Request, res: Response) => { const result = CreateUserSchema.safeParse(req.body); if (!result.success) { return res.status(400).json({ errors: result.error.flatten() }); } const user = await userService.create(result.data); res.status(201).json(user); }); ``` ## State Management ### Zustand Store ```typescript import { create } from "zustand"; interface CartStore { items: CartItem[]; addItem: (item: CartItem) => void; removeItem: (id: string) => void; total: () => number; } export const useCartStore = create<CartStore>((set, get) => ({ items: [], addItem: (item) => set((state) => ({ items: [...state.items, item] })), removeItem: (id) => set((state) => ({ items: state.items.filter(i => i.id !== id) })), total: () => get().items.reduce((sum, item) => sum + item.price, 0), })); ``` ## Type-safe API (tRPC / Zod) ### Zod Schema Validation ```typescript import { z } from "zod"; export const UserSchema = z.object({ id: z.string().uuid(), name: z.string().min(1).max(100), email: z.string().email(), role: z.enum(["admin", "user", "guest"]), createdAt: z.coerce.date(), }); export type User = z.infer<typeof UserSchema>; ``` ## Error Handling ```typescript class AppError extends Error { constructor( message: string, public statusCode: number = 500, public code: string = "INTERNAL_ERROR" ) { super(message); this.name = "AppError"; } } // Result pattern (no exceptions) type Result<T, E = Error> = | { success: true; data: T } | { success: false; error: E }; function parseUser(raw: unknown): Result<User> { const result = UserSchema.safeParse(raw); if (result.success) return { success: true, data: result.data }; return { success: false, error: new Error(result.error.message) }; } ``` ## Testing with Vitest ```typescript import { describe, it, expect, vi } from "vitest"; describe("UserService", () => { it("creates user with valid data", async () => { const mockRepo = { create: vi.fn().mockResolvedValue({ id: "1", name: "Test" }) }; const service = new UserService(mockRepo); const user = await service.create({ name: "Test", email: "t@t.com" }); expect(user.id).toBe("1"); expect(mockRepo.create).toHaveBeenCalledOnce(); }); }); ``` ## Anti-Patterns - `any` type usage (use `unknown` and narrow) - Non-null assertions `!` without checks - `as` type casting instead of type guards - Mutable state in React (use immutable updates) - Missing error boundaries in React - Barrel exports that break tree-shaking
在 GitHub 查看