@vpxa/aikit 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/package.json +1 -1
  2. package/packages/cli/dist/aikit-init.js +1 -1
  3. package/packages/cli/dist/commands/init/constants.d.ts +1 -1
  4. package/packages/cli/dist/commands/init/constants.js +1 -1
  5. package/packages/cli/dist/commands/init/user.js +1 -1
  6. package/packages/core/dist/index.d.ts +2 -2
  7. package/packages/core/dist/index.js +1 -1
  8. package/packages/core/dist/types.d.ts +12 -2
  9. package/packages/core/dist/types.js +1 -1
  10. package/packages/indexer/dist/incremental-indexer.d.ts +16 -0
  11. package/packages/indexer/dist/incremental-indexer.js +1 -1
  12. package/packages/indexer/dist/index.d.ts +2 -1
  13. package/packages/indexer/dist/index.js +1 -1
  14. package/packages/indexer/dist/smart-index-scheduler.d.ts +36 -0
  15. package/packages/indexer/dist/smart-index-scheduler.js +1 -0
  16. package/packages/server/dist/config.d.ts +3 -1
  17. package/packages/server/dist/config.js +1 -1
  18. package/packages/server/dist/index.js +1 -1
  19. package/packages/server/dist/server.d.ts +6 -2
  20. package/packages/server/dist/server.js +2 -2
  21. package/packages/server/dist/tools/context.tools.d.ts +1 -1
  22. package/packages/server/dist/tools/context.tools.js +2 -2
  23. package/packages/server/dist/tools/graph.tool.js +7 -2
  24. package/packages/store/dist/graph-store.interface.d.ts +42 -1
  25. package/packages/store/dist/index.d.ts +2 -2
  26. package/packages/store/dist/sqlite-graph-store.d.ts +10 -1
  27. package/packages/store/dist/sqlite-graph-store.js +49 -17
  28. package/packages/tools/dist/graph-query.d.ts +14 -2
  29. package/packages/tools/dist/graph-query.js +1 -1
  30. package/packages/tools/dist/trace.d.ts +16 -2
  31. package/packages/tools/dist/trace.js +2 -2
  32. package/scaffold/definitions/bodies.mjs +24 -0
  33. package/scaffold/definitions/prompts.mjs +22 -3
  34. package/scaffold/definitions/protocols.mjs +22 -0
  35. package/scaffold/general/agents/Architect-Reviewer-Alpha.agent.md +6 -0
  36. package/scaffold/general/agents/Architect-Reviewer-Beta.agent.md +6 -0
  37. package/scaffold/general/agents/Code-Reviewer-Alpha.agent.md +6 -0
  38. package/scaffold/general/agents/Code-Reviewer-Beta.agent.md +6 -0
  39. package/scaffold/general/agents/Debugger.agent.md +6 -0
  40. package/scaffold/general/agents/Documenter.agent.md +6 -0
  41. package/scaffold/general/agents/Explorer.agent.md +6 -0
  42. package/scaffold/general/agents/Frontend.agent.md +6 -0
  43. package/scaffold/general/agents/Implementer.agent.md +6 -0
  44. package/scaffold/general/agents/Orchestrator.agent.md +69 -0
  45. package/scaffold/general/agents/Planner.agent.md +18 -0
  46. package/scaffold/general/agents/Refactor.agent.md +6 -0
  47. package/scaffold/general/agents/Researcher-Alpha.agent.md +6 -0
  48. package/scaffold/general/agents/Researcher-Beta.agent.md +6 -0
  49. package/scaffold/general/agents/Researcher-Delta.agent.md +6 -0
  50. package/scaffold/general/agents/Researcher-Gamma.agent.md +6 -0
  51. package/scaffold/general/agents/Security.agent.md +6 -0
  52. package/scaffold/general/agents/_shared/code-agent-base.md +22 -0
  53. package/scaffold/general/prompts/ask.prompt.md +1 -1
  54. package/scaffold/general/prompts/debug.prompt.md +1 -0
  55. package/scaffold/general/prompts/implement.prompt.md +1 -0
  56. package/scaffold/general/prompts/plan.prompt.md +1 -1
  57. package/scaffold/general/prompts/review.prompt.md +1 -1
  58. package/scaffold/general/skills/frontend-design/SKILL.md +225 -0
  59. package/scaffold/general/skills/react/SKILL.md +297 -0
  60. package/scaffold/general/skills/typescript/SKILL.md +393 -0
@@ -0,0 +1,297 @@
1
+ # React
2
+
3
+ > Comprehensive React development patterns — component architecture, React 19 APIs, Server Components, TypeScript integration, and performance optimization. Synthesized from react-dev patterns, react-patterns (React 19), and Vercel React best practices.
4
+
5
+ ## When to Use
6
+
7
+ **MANDATORY** for the Frontend agent on every React task. Also use when:
8
+ - Building React components, hooks, or pages
9
+ - Working with Server Components or Server Actions
10
+ - Optimizing React performance (re-renders, bundle size, data fetching)
11
+ - Reviewing React code for correctness and best practices
12
+
13
+ ## React 19 Quick Reference
14
+
15
+ | API | Use Case | Key Change |
16
+ |-----|----------|------------|
17
+ | `ref` as prop | Access DOM/component instance | No more `forwardRef` wrapper |
18
+ | `use()` | Read promises/context in render | Replaces `useContext`, enables async |
19
+ | `useActionState` | Form submission state + error | Replaces `useFormState` |
20
+ | `useOptimistic` | Instant UI feedback | Optimistic updates before server confirms |
21
+ | `useTransition` | Non-urgent state updates | `isPending` for loading states |
22
+ | `<form action>` | Server Actions in forms | Direct server function binding |
23
+ | Server Components | Zero-bundle components | Default in App Router, no `"use client"` |
24
+ | Server Actions | Server mutations | `"use server"` functions, form actions |
25
+
26
+ ## Component Patterns
27
+
28
+ ### Extend Native Elements
29
+ ```tsx
30
+ type ButtonProps = React.ComponentProps<"button"> & {
31
+ variant?: "primary" | "secondary" | "ghost";
32
+ size?: "sm" | "md" | "lg";
33
+ };
34
+
35
+ function Button({ variant = "primary", size = "md", className, ...props }: ButtonProps) {
36
+ return <button className={cn(variants[variant], sizes[size], className)} {...props} />;
37
+ }
38
+ ```
39
+
40
+ ### Discriminated Union Props
41
+ ```tsx
42
+ type ModalProps =
43
+ | { variant: "alert"; message: string; onConfirm: () => void }
44
+ | { variant: "form"; children: React.ReactNode; onSubmit: (data: FormData) => void };
45
+
46
+ function Modal(props: ModalProps) {
47
+ switch (props.variant) {
48
+ case "alert": return <AlertModal {...props} />;
49
+ case "form": return <FormModal {...props} />;
50
+ }
51
+ }
52
+ ```
53
+
54
+ ### Generic Components
55
+ ```tsx
56
+ type TableProps<T> = {
57
+ data: T[];
58
+ columns: { key: keyof T; header: string; render?: (value: T[keyof T], row: T) => React.ReactNode }[];
59
+ onRowClick?: (row: T) => void;
60
+ };
61
+
62
+ function Table<T extends Record<string, unknown>>({ data, columns, onRowClick }: TableProps<T>) {
63
+ // ...
64
+ }
65
+ ```
66
+
67
+ ### Children Typing
68
+ ```tsx
69
+ // Specific children
70
+ type Props = { children: React.ReactElement<TabProps>[] };
71
+
72
+ // Render function children
73
+ type Props = { children: (data: T) => React.ReactNode };
74
+
75
+ // String only
76
+ type Props = { children: string };
77
+ ```
78
+
79
+ ## Ref as Prop (React 19)
80
+
81
+ ```tsx
82
+ // React 19: pass ref directly, no forwardRef needed
83
+ function Input({ ref, ...props }: React.ComponentProps<"input">) {
84
+ return <input ref={ref} {...props} />;
85
+ }
86
+
87
+ // Cleanup function (new in React 19)
88
+ function MeasuredDiv({ ref, ...props }: React.ComponentProps<"div">) {
89
+ return (
90
+ <div
91
+ ref={(node) => {
92
+ if (node) measureElement(node);
93
+ return () => cleanupMeasurement(); // cleanup on unmount
94
+ }}
95
+ {...props}
96
+ />
97
+ );
98
+ }
99
+ ```
100
+
101
+ ## Server Components & Actions
102
+
103
+ ### Server Component (default — no directive needed)
104
+ ```tsx
105
+ // app/users/page.tsx — Server Component (default)
106
+ import { db } from "@/lib/db";
107
+
108
+ export default async function UsersPage() {
109
+ const users = await db.query.users.findMany(); // Direct DB access
110
+ return <UserList users={users} />; // Pass data to client
111
+ }
112
+ ```
113
+
114
+ ### Client Component (explicit opt-in)
115
+ ```tsx
116
+ "use client";
117
+ import { useState, useOptimistic, useTransition } from "react";
118
+
119
+ export function Counter({ initialCount }: { initialCount: number }) {
120
+ const [count, setCount] = useState(initialCount);
121
+ return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
122
+ }
123
+ ```
124
+
125
+ ### Server Action with Form
126
+ ```tsx
127
+ // actions.ts
128
+ "use server";
129
+ import { z } from "zod";
130
+
131
+ const schema = z.object({ name: z.string().min(1), email: z.string().email() });
132
+
133
+ export async function createUser(_prev: unknown, formData: FormData) {
134
+ const result = schema.safeParse(Object.fromEntries(formData));
135
+ if (!result.success) return { error: result.error.flatten().fieldErrors };
136
+ await db.insert(users).values(result.data);
137
+ return { success: true };
138
+ }
139
+ ```
140
+
141
+ ```tsx
142
+ "use client";
143
+ import { useActionState } from "react";
144
+ import { createUser } from "./actions";
145
+
146
+ export function CreateUserForm() {
147
+ const [state, action, isPending] = useActionState(createUser, null);
148
+ return (
149
+ <form action={action}>
150
+ <input name="name" required />
151
+ {state?.error?.name && <p className="text-red-500">{state.error.name}</p>}
152
+ <input name="email" type="email" required />
153
+ {state?.error?.email && <p className="text-red-500">{state.error.email}</p>}
154
+ <button disabled={isPending}>{isPending ? "Creating..." : "Create"}</button>
155
+ </form>
156
+ );
157
+ }
158
+ ```
159
+
160
+ ### Optimistic Updates
161
+ ```tsx
162
+ "use client";
163
+ import { useOptimistic } from "react";
164
+
165
+ function TodoList({ todos, addTodo }: { todos: Todo[]; addTodo: (text: string) => Promise<void> }) {
166
+ const [optimisticTodos, addOptimistic] = useOptimistic(
167
+ todos,
168
+ (state, newTodo: string) => [...state, { id: "temp", text: newTodo, pending: true }]
169
+ );
170
+
171
+ async function handleAdd(formData: FormData) {
172
+ const text = formData.get("text") as string;
173
+ addOptimistic(text);
174
+ await addTodo(text);
175
+ }
176
+
177
+ return (
178
+ <form action={handleAdd}>
179
+ <input name="text" />
180
+ <button type="submit">Add</button>
181
+ <ul>
182
+ {optimisticTodos.map(t => (
183
+ <li key={t.id} style={{ opacity: t.pending ? 0.5 : 1 }}>{t.text}</li>
184
+ ))}
185
+ </ul>
186
+ </form>
187
+ );
188
+ }
189
+ ```
190
+
191
+ ## Event Handler Types
192
+
193
+ ```tsx
194
+ // Always use specific event types
195
+ onClick: (e: React.MouseEvent<HTMLButtonElement>) => void
196
+ onChange: (e: React.ChangeEvent<HTMLInputElement>) => void
197
+ onSubmit: (e: React.FormEvent<HTMLFormElement>) => void
198
+ onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void
199
+ onFocus: (e: React.FocusEvent<HTMLInputElement>) => void
200
+ onDrag: (e: React.DragEvent<HTMLDivElement>) => void
201
+ ```
202
+
203
+ ## Hooks Typing
204
+
205
+ ```tsx
206
+ // useState with union
207
+ const [status, setStatus] = useState<"idle" | "loading" | "error">("idle");
208
+
209
+ // useRef for DOM — pass null, get RefObject
210
+ const inputRef = useRef<HTMLInputElement>(null);
211
+
212
+ // useRef for mutable value — no null, get MutableRefObject
213
+ const intervalRef = useRef<number>(0);
214
+
215
+ // useReducer with discriminated actions
216
+ type Action = { type: "increment" } | { type: "set"; payload: number };
217
+ const [count, dispatch] = useReducer((state: number, action: Action) => {
218
+ switch (action.type) {
219
+ case "increment": return state + 1;
220
+ case "set": return action.payload;
221
+ }
222
+ }, 0);
223
+
224
+ // Custom hook: return as const for tuple types
225
+ function useToggle(initial = false) {
226
+ const [value, setValue] = useState(initial);
227
+ const toggle = useCallback(() => setValue(v => !v), []);
228
+ return [value, toggle] as const;
229
+ }
230
+
231
+ // useContext with null guard
232
+ const ctx = useContext(ThemeContext);
233
+ if (!ctx) throw new Error("useTheme must be used within ThemeProvider");
234
+ ```
235
+
236
+ ## Performance Rules
237
+
238
+ ### Prevent Async Waterfalls
239
+ ```tsx
240
+ // BAD — sequential fetching
241
+ const user = await getUser(id);
242
+ const posts = await getPosts(user.id); // Waits for user first
243
+ const comments = await getComments(posts[0].id); // Waits for posts
244
+
245
+ // GOOD — parallel where possible
246
+ const [user, posts] = await Promise.all([getUser(id), getPosts(id)]);
247
+ ```
248
+
249
+ ### Bundle Size
250
+ - `dynamic(() => import("./HeavyComponent"))` — lazy load below-fold components
251
+ - Tree-shake: use named exports, avoid `import *`
252
+ - Analyze bundle: `@next/bundle-analyzer` to find bloat
253
+ - Code-split by route — each page loads only its own JS
254
+ - Avoid importing entire libraries: `import { debounce } from "lodash-es"` not `import _ from "lodash"`
255
+
256
+ ### Server-Side Performance
257
+ - Default to Server Components — zero JS shipped to client
258
+ - Stream with Suspense: wrap slow data fetchers in `<Suspense fallback={<Skeleton />}>`
259
+ - Cache expensive computations with `"use cache"` directive
260
+ - Avoid serializing large objects across server/client boundary
261
+
262
+ ### Client-Side Data Fetching
263
+ - Use SWR or React Query — automatic caching, revalidation, error retry
264
+ - Stale-while-revalidate: show cached data instantly, refresh in background
265
+ - Error boundaries: `<ErrorBoundary>` wrapping data-dependent trees
266
+ - Prefetch on hover/viewport for likely next navigations
267
+
268
+ ### Re-render Optimization
269
+ - React Compiler (React 19): auto-memoizes — try this first before manual `useMemo`/`useCallback`
270
+ - If no compiler: `useMemo` for expensive computations, `useCallback` for stable function references
271
+ - Extract static JSX outside components — constants don't re-create
272
+ - Split context: separate frequently-changing state from rarely-changing state
273
+ - `React.memo()` on components receiving only primitive props
274
+
275
+ ### Rendering Performance
276
+ - **Virtualize** lists > 100 items: `@tanstack/react-virtual`, `react-window`
277
+ - Defer heavy computations with `useDeferredValue`
278
+ - Batch state updates (React 18+ does this automatically in event handlers)
279
+ - Avoid reading DOM layout during renders (force sync layout = jank)
280
+
281
+ ### Advanced Patterns
282
+ - Progressive hydration: load and hydrate components as they enter viewport
283
+ - Concurrent features: `useTransition` for non-blocking state updates
284
+ - Suspense caching: combine `<Suspense>` with data cache for instant page transitions
285
+ - React Compiler adoption: enable gradually, check for unsafe patterns first
286
+
287
+ ## Decision Flow
288
+
289
+ When implementing a React feature:
290
+
291
+ 1. **Server or Client?** → If it uses browser APIs, event handlers, or useState → Client. Everything else → Server.
292
+ 2. **Data fetching?** → Server Component for initial data. SWR/React Query for client-side mutations.
293
+ 3. **Form?** → Server Action + `useActionState` + Zod validation.
294
+ 4. **Optimistic?** → `useOptimistic` for instant feedback.
295
+ 5. **Loading?** → `<Suspense>` with skeleton fallback.
296
+ 6. **Performance?** → Try React Compiler first. Then manual memo. Then virtualization. Then code splitting.
297
+ 7. **Error?** → Error boundaries for rendering errors. try/catch for Server Actions.
@@ -0,0 +1,393 @@
1
+ # TypeScript
2
+
3
+ > Comprehensive TypeScript development patterns — type system performance, compiler configuration, advanced types, type safety, async patterns, module organization, and runtime optimization. Synthesized from pproenca TypeScript rules, TypeScript 6.0 features, wshobson advanced types and modern JS patterns, and Jeffallan typescript-pro patterns.
4
+
5
+ ## When to Use
6
+
7
+ **MANDATORY** for the Implementer agent on every TypeScript task. Also use when:
8
+ - Writing or reviewing TypeScript code
9
+ - Configuring `tsconfig.json` or compiler options
10
+ - Designing type-safe APIs, libraries, or utilities
11
+ - Optimizing type-check performance or build times
12
+
13
+ ## Type System Performance
14
+
15
+ These rules prevent slow type-checking and IDE lag:
16
+
17
+ ### Prefer Flat Unions Over Deep Conditionals
18
+ ```tsx
19
+ // BAD — O(n²) type checking with deep conditionals
20
+ type DeepResolve<T> = T extends Promise<infer U> ? DeepResolve<U> : T extends Array<infer V> ? DeepResolve<V>[] : T;
21
+
22
+ // GOOD — flat unions check in O(n)
23
+ type Status = "idle" | "loading" | "success" | "error";
24
+ type Result = SuccessResult | ErrorResult | PendingResult;
25
+ ```
26
+
27
+ ### Interface Extends Over Intersection
28
+ ```tsx
29
+ // BAD — intersection types are expensive to compute
30
+ type Extended = BaseType & { extra: string } & { more: number };
31
+
32
+ // GOOD — interface extends is cached by the compiler
33
+ interface Extended extends BaseType {
34
+ extra: string;
35
+ more: number;
36
+ }
37
+ ```
38
+
39
+ ### Rules
40
+ - **Avoid recursive conditional types** deeper than 3 levels — use iterative mapped types instead
41
+ - **Minimize computed types** in hot paths (function parameters, return types used in many places)
42
+ - **Use `interface` for object shapes**, `type` for unions, intersections, and mapped types
43
+ - **Annotate complex return types** explicitly — don't force the compiler to infer through 5 layers
44
+ - **Avoid generic defaults that trigger deep inference** — provide explicit type arguments at call sites
45
+ - **Break circular type references** — extract shared shapes into separate interfaces
46
+
47
+ ## Compiler Configuration
48
+
49
+ ### Strict Mode (all projects)
50
+ ```jsonc
51
+ {
52
+ "compilerOptions": {
53
+ "strict": true, // Enables ALL strict checks
54
+ "noUncheckedIndexedAccess": true, // arr[0] is T | undefined
55
+ "exactOptionalProperties": true, // undefined ≠ missing
56
+ "noFallthroughCasesInSwitch": true,
57
+ "forceConsistentCasingInFileNames": true,
58
+ "isolatedModules": true, // Required for most bundlers
59
+ "verbatimModuleSyntax": true // Explicit import/export type
60
+ }
61
+ }
62
+ ```
63
+
64
+ ### Build Performance
65
+ ```jsonc
66
+ {
67
+ "compilerOptions": {
68
+ "incremental": true, // Cache type-check results
69
+ "tsBuildInfoFile": ".tsbuildinfo",
70
+ "skipLibCheck": true // Skip .d.ts checking (safe for apps)
71
+ }
72
+ }
73
+ ```
74
+
75
+ ### Project References (monorepos)
76
+ ```jsonc
77
+ // tsconfig.json (root)
78
+ {
79
+ "references": [
80
+ { "path": "packages/core" },
81
+ { "path": "packages/server" },
82
+ { "path": "packages/cli" }
83
+ ]
84
+ }
85
+
86
+ // packages/core/tsconfig.json
87
+ {
88
+ "compilerOptions": {
89
+ "composite": true,
90
+ "declaration": true,
91
+ "declarationMap": true
92
+ }
93
+ }
94
+ ```
95
+
96
+ ### TypeScript 6.0+ Features
97
+ - **`#/` subpath imports**: `import { utils } from "#/lib/utils"` — no more `../../../` relative paths. Configure in `package.json` `"imports"` field.
98
+ - **`es2025` target**: Set, Iterator, Promise.withResolvers, RegExp v flag
99
+ - **`--noCheck`**: Skip type-checking in CI (when pre-checked) for faster builds
100
+ - **`--stableTypeOrdering`**: Deterministic declaration output for reproducible builds
101
+ - **`isolatedDeclarations`**: Generate `.d.ts` without type-checking — enables parallel builds
102
+
103
+ ## Advanced Types
104
+
105
+ ### Constrained Generics
106
+ ```tsx
107
+ // Constrain to ensure property exists
108
+ function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
109
+ return obj[key];
110
+ }
111
+
112
+ // Constrain with interface
113
+ function merge<T extends Record<string, unknown>>(target: T, source: Partial<T>): T {
114
+ return { ...target, ...source };
115
+ }
116
+ ```
117
+
118
+ ### Conditional Types
119
+ ```tsx
120
+ // Extract return type from async function
121
+ type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
122
+
123
+ // Distributive conditional
124
+ type NonNullableDeep<T> = T extends null | undefined ? never : T extends object ? { [K in keyof T]: NonNullableDeep<T[K]> } : T;
125
+
126
+ // Infer from function
127
+ type Parameters<T> = T extends (...args: infer P) => unknown ? P : never;
128
+ ```
129
+
130
+ ### Mapped Types
131
+ ```tsx
132
+ // Make all properties optional recursively
133
+ type DeepPartial<T> = { [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P] };
134
+
135
+ // Remove readonly
136
+ type Mutable<T> = { -readonly [P in keyof T]: T[P] };
137
+
138
+ // Key remapping
139
+ type Getters<T> = { [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K] };
140
+ ```
141
+
142
+ ### Template Literal Types
143
+ ```tsx
144
+ // Event name typing
145
+ type EventName<T extends string> = `on${Capitalize<T>}`;
146
+ type Events = EventName<"click" | "focus" | "blur">; // "onClick" | "onFocus" | "onBlur"
147
+
148
+ // Route parameter extraction
149
+ type ExtractParams<T extends string> =
150
+ T extends `${string}:${infer Param}/${infer Rest}`
151
+ ? Param | ExtractParams<Rest>
152
+ : T extends `${string}:${infer Param}`
153
+ ? Param
154
+ : never;
155
+ type Params = ExtractParams<"/users/:id/posts/:postId">; // "id" | "postId"
156
+ ```
157
+
158
+ ### Utility Type Patterns
159
+ ```tsx
160
+ // Deep readonly
161
+ type DeepReadonly<T> = { readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P] };
162
+
163
+ // Make specific keys required
164
+ type RequireKeys<T, K extends keyof T> = T & Required<Pick<T, K>>;
165
+
166
+ // Object paths as union
167
+ type Paths<T, D extends number = 3> = [D] extends [never]
168
+ ? never
169
+ : T extends object
170
+ ? { [K in keyof T]-?: K extends string ? `${K}` | `${K}.${Paths<T[K]>}` : never }[keyof T]
171
+ : never;
172
+ ```
173
+
174
+ ## Type Safety Patterns
175
+
176
+ ### Branded Types
177
+ ```tsx
178
+ // Prevent mixing IDs of different entities
179
+ type UserId = string & { readonly __brand: "UserId" };
180
+ type OrderId = string & { readonly __brand: "OrderId" };
181
+
182
+ function createUserId(id: string): UserId { return id as UserId; }
183
+ function createOrderId(id: string): OrderId { return id as OrderId; }
184
+
185
+ function getUser(id: UserId) { /* ... */ }
186
+ getUser(createOrderId("123")); // TS Error! OrderId is not UserId
187
+ ```
188
+
189
+ ### Discriminated Unions with Exhaustive Matching
190
+ ```tsx
191
+ type Shape =
192
+ | { kind: "circle"; radius: number }
193
+ | { kind: "rect"; width: number; height: number }
194
+ | { kind: "triangle"; base: number; height: number };
195
+
196
+ function area(shape: Shape): number {
197
+ switch (shape.kind) {
198
+ case "circle": return Math.PI * shape.radius ** 2;
199
+ case "rect": return shape.width * shape.height;
200
+ case "triangle": return 0.5 * shape.base * shape.height;
201
+ default: {
202
+ const _exhaustive: never = shape; // Compile error if case missed
203
+ return _exhaustive;
204
+ }
205
+ }
206
+ }
207
+ ```
208
+
209
+ ### Result Pattern
210
+ ```tsx
211
+ type Result<T, E = Error> = { ok: true; value: T } | { ok: false; error: E };
212
+
213
+ function ok<T>(value: T): Result<T, never> { return { ok: true, value }; }
214
+ function err<E>(error: E): Result<never, E> { return { ok: false, error }; }
215
+
216
+ async function parseConfig(path: string): Promise<Result<Config, ParseError>> {
217
+ try {
218
+ const raw = await readFile(path, "utf-8");
219
+ return ok(JSON.parse(raw));
220
+ } catch (e) {
221
+ return err(new ParseError(`Failed to parse ${path}`, { cause: e }));
222
+ }
223
+ }
224
+
225
+ // Usage — forces error handling
226
+ const result = await parseConfig("config.json");
227
+ if (!result.ok) {
228
+ console.error(result.error.message);
229
+ process.exit(1);
230
+ }
231
+ const config = result.value; // Type-narrowed to Config
232
+ ```
233
+
234
+ ## Async Patterns
235
+
236
+ ### Parallel Execution
237
+ ```tsx
238
+ // Promise.all — fail-fast on first rejection
239
+ const [users, posts] = await Promise.all([getUsers(), getPosts()]);
240
+
241
+ // Promise.allSettled — get all results regardless of failures
242
+ const results = await Promise.allSettled([getUsers(), getPosts(), getComments()]);
243
+ for (const r of results) {
244
+ if (r.status === "fulfilled") process(r.value);
245
+ else logError(r.reason);
246
+ }
247
+ ```
248
+
249
+ ### AbortController
250
+ ```tsx
251
+ async function fetchWithTimeout(url: string, timeoutMs: number): Promise<Response> {
252
+ const controller = new AbortController();
253
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
254
+ try {
255
+ return await fetch(url, { signal: controller.signal });
256
+ } finally {
257
+ clearTimeout(timeout);
258
+ }
259
+ }
260
+ ```
261
+
262
+ ### Async Iterators
263
+ ```tsx
264
+ async function* paginate<T>(fetcher: (page: number) => Promise<T[]>): AsyncGenerator<T> {
265
+ let page = 0;
266
+ while (true) {
267
+ const items = await fetcher(page++);
268
+ if (items.length === 0) break;
269
+ yield* items;
270
+ }
271
+ }
272
+
273
+ // Usage
274
+ for await (const user of paginate(fetchUsersPage)) {
275
+ processUser(user);
276
+ }
277
+ ```
278
+
279
+ ## Module Organization
280
+
281
+ ### Barrel File Performance
282
+ ```tsx
283
+ // BAD — barrel files cause entire module tree to load
284
+ // index.ts
285
+ export * from "./userService";
286
+ export * from "./orderService";
287
+ export * from "./paymentService";
288
+
289
+ // GOOD — direct imports skip barrel overhead
290
+ import { UserService } from "./services/userService";
291
+ ```
292
+
293
+ ### Type-Only Imports
294
+ ```tsx
295
+ // Always use type-only imports for types
296
+ import type { User, CreateUserDto } from "./types";
297
+ import { UserService } from "./userService";
298
+ // With verbatimModuleSyntax, this is enforced
299
+ ```
300
+
301
+ ### Re-export Patterns
302
+ ```tsx
303
+ // Public API surface — explicit re-exports
304
+ export { UserService } from "./userService";
305
+ export type { User, CreateUserDto } from "./types";
306
+ // Don't export internal implementation details
307
+ ```
308
+
309
+ ## Memory & Runtime
310
+
311
+ ### WeakRef for Caches
312
+ ```tsx
313
+ class WeakCache<K extends object, V> {
314
+ private cache = new Map<K, WeakRef<V & object>>();
315
+ private registry = new FinalizationRegistry<K>(key => this.cache.delete(key));
316
+
317
+ set(key: K, value: V & object): void {
318
+ this.cache.set(key, new WeakRef(value));
319
+ this.registry.register(value, key);
320
+ }
321
+
322
+ get(key: K): V | undefined {
323
+ return this.cache.get(key)?.deref();
324
+ }
325
+ }
326
+ ```
327
+
328
+ ### Efficient Data Structures
329
+ ```tsx
330
+ // Use Map/Set for frequent lookups
331
+ const userIndex = new Map<string, User>(); // O(1) lookup
332
+ const activeIds = new Set<string>(); // O(1) has/add/delete
333
+
334
+ // NOT plain objects for dynamic keys
335
+ const userIndex: Record<string, User> = {}; // Slower for frequent mutations
336
+ ```
337
+
338
+ ### Runtime Rules
339
+ - Minimize `Reflect.metadata` and decorator reflection — adds runtime overhead
340
+ - Prefer `structuredClone()` over `JSON.parse(JSON.stringify())` for deep cloning
341
+ - Use `Object.freeze()` for truly immutable constants
342
+ - Avoid `eval()`, `new Function()`, and dynamic `require()` — security + performance issues
343
+
344
+ ## Modern JavaScript Patterns
345
+
346
+ ### Nullish Handling
347
+ ```tsx
348
+ const port = config.port ?? 3000; // Only for null/undefined
349
+ const name = user?.profile?.displayName; // Optional chaining
350
+ const normalized = (input ??= defaultValue); // Nullish assignment
351
+ ```
352
+
353
+ ### Immutable Updates
354
+ ```tsx
355
+ // Object spread for shallow updates
356
+ const updated = { ...user, name: "New Name" };
357
+
358
+ // structuredClone for deep copy
359
+ const deep = structuredClone(complexObject);
360
+
361
+ // Array immutable operations
362
+ const added = [...items, newItem];
363
+ const removed = items.filter(i => i.id !== targetId);
364
+ const updated = items.map(i => i.id === targetId ? { ...i, ...changes } : i);
365
+ ```
366
+
367
+ ### Pipe Pattern
368
+ ```tsx
369
+ function pipe<T>(value: T, ...fns: Array<(v: unknown) => unknown>): unknown {
370
+ return fns.reduce((acc, fn) => fn(acc), value as unknown);
371
+ }
372
+
373
+ // Usage
374
+ const result = pipe(
375
+ rawData,
376
+ validate,
377
+ normalize,
378
+ transform,
379
+ serialize
380
+ );
381
+ ```
382
+
383
+ ## Decision Flow
384
+
385
+ When writing TypeScript:
386
+
387
+ 1. **Interface or Type?** → Object shape = interface. Union/intersection/mapped = type.
388
+ 2. **Generic needed?** → If the function works with multiple types and you need to preserve the type → yes. Otherwise keep it simple.
389
+ 3. **Strict enough?** → Enable all strict flags. Use branded types for domain IDs. Use discriminated unions for variants.
390
+ 4. **Performance?** → Check: Are there deep conditional types? Circular references? Massive unions? Simplify if so.
391
+ 5. **Import style?** → `import type` for types. Direct imports, not barrel files. Named exports, not default.
392
+ 6. **Error handling?** → Result pattern for expected errors. throw for unexpected/programmer errors.
393
+ 7. **Async?** → Promise.all for parallel. AbortController for timeouts. AsyncGenerator for streams.