brainstorming
Apply when generating ideas, exploring solution space, or facilitating divergent thinking before committing to an approach.
Apply when writing TypeScript code. Strict types, discriminated unions, async patterns, and runtime safety.
$ npx -y skills add sordi-ai/skill-everything --skill typescript --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/typescriptContext preview
The summary Claude sees to decide when to auto-load this skill.
Apply when writing TypeScript code. Strict types, discriminated unions, async patterns, and runtime safety.
name: typescript description: Apply when writing TypeScript code. Strict types, discriminated unions, async patterns, and runtime safety. license: MIT version: 1.0.0 tokens_target: 2500 triggers: - typescript code - strict types - async typescript loads_after: - code-quality supersedes: []
<!-- target: ~2500 tokens (real tiktoken count) | 17 rules with severity classification -->
**Purpose:** Prevents the TypeScript-specific mistakes LLMs make repeatedly — weak types, unsafe assertions, and patterns that compile but fail at runtime.
**Where these rules don't strictly apply:** test fixtures, generated types (e.g. from GraphQL codegen, OpenAPI generators, Prisma), declaration files (`*.d.ts`) for untyped third-party libraries, and migration scripts may legitimately differ. The rules below apply to **production application code**.
---
1. **MUST: Never use `any`. Use `unknown` and narrow it.** `any` disables the type checker entirely. `unknown` forces you to prove the type before use. *Exception: third-party libraries without types and explicit dynamic-data boundaries (e.g. JSON parse at the API edge), with a comment explaining why.*
// Wrong
function parse(data: any) { return data.name; }
// Correct
function parse(data: unknown): string {
if (typeof data === 'object' && data !== null && 'name' in data) {
return String((data as { name: unknown }).name);
}
throw new Error('Invalid data shape');
}2. **AVOID: `Object` or `{}` as a type.** Both accept nearly everything. Use `Record<string, unknown>` for arbitrary objects or define an explicit interface.
// Wrong
function merge(a: {}, b: Object): {} { ... }
// Correct
function merge<T extends Record<string, unknown>>(a: T, b: Partial<T>): T { ... }3. **SHOULD: Use `as` only when you know more than the compiler — and document why.** Prefer type guards or `satisfies` instead.
// Wrong — silences the error, hides the bug
const user = response.data as User;
// Correct — validate first
function isUser(v: unknown): v is User {
return typeof v === 'object' && v !== null && 'id' in v && 'email' in v;
}
const user = isUser(response.data) ? response.data : null;4. **SHOULD: Mark immutable data `readonly`.** Prevents accidental mutation and communicates intent.
// Avoid
function process(ids: string[]) { ids.push('extra'); }
// Prefer
function process(ids: readonly string[]) { /* ids.push() is a compile error */ }5. **MUST: Enable `strictNullChecks` and handle every `T | undefined`.** Optional chaining `?.` returns `undefined` — always handle that branch.
// Wrong const name = user?.profile.name.toUpperCase(); // crashes if name is undefined // Correct const name = user?.profile.name?.toUpperCase() ?? 'Anonymous';
6. **SHOULD: Use branded types for IDs.** Prevents passing a `UserId` where an `OrderId` is expected — both are `string` at runtime.
type UserId = string & { readonly _brand: 'UserId' };
type OrderId = string & { readonly _brand: 'OrderId' };
function createUserId(raw: string): UserId { return raw as UserId; }
function getUser(id: UserId): User { ... }
// getUser(orderId) → compile error---
7. **SHOULD: Use discriminated unions for state, not optional fields.** Optional fields force you to reason about all combinations. A discriminated union makes illegal states unrepresentable.
// Avoid — 8 possible combinations, most invalid
type Request = { loading?: boolean; data?: User; error?: Error };
// Prefer — exactly 3 valid states
type Request =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: User }
| { status: 'error'; error: Error };8. **SHOULD: Use `satisfies` to validate shape without widening the type.** `as const` preserves literals; `satisfies` validates against an interface without losing them.
const config = {
host: 'localhost',
port: 5432,
} satisfies DatabaseConfig;
// config.port is still typed as 5432, not number9. **SHOULD: Use `const` objects instead of `enum`.** Enums emit runtime code, have surprising reverse-mapping behavior, and are not idiomatic TypeScript.
// Avoid
enum Direction { Up, Down, Left, Right }
// Prefer
const Direction = { Up: 'Up', Down: 'Down', Left: 'Left', Right: 'Right' } as const;
type Direction = typeof Direction[keyof typeof Direction];10. **AVOID: Barrel `index.ts` re-exports in large modules.** They cause circular dependency chains that are hard to debug. Export directly from source files or use explicit named re-exports only.
// Wrong — index.ts re-exports everything, A imports B through index, B imports A through index
export * from './userService';
export * from './orderService';
// Correct — import directly
import { getUser } from './services/userService';---
11. **MUST: Type your thrown errors explicitly.** `catch (e)` gives you `unknown` in strict mode. Narrow before accessing properties.
try {
await fetchUser(id);
} catch (e) {
// Wrong: e.message — e is unknown
// Correct:
const message = e instanceof Error ? e.message : String(e);
logger.error('fetchUser failed', { message, id });
}12. **SHOULD: Use `Result` types for expected failures instead of throwing.** Throwing for control flow forces callers to know which functions throw and what.
typ
Git-versioned agent memory: agents that never make the same mistake twice. Anthropic-Skill folder standard, multi-runtime (Claude Code, Cursor, Gemini CLI, OpenCode).
Repo: sordi-ai/skill-everything
Apply when generating ideas, exploring solution space, or facilitating divergent thinking before committing to an approach.
Apply when closing out a feature branch — pre-merge checklist, rebase, CI verification, cleanup, and post-merge steps.
Apply when writing or refactoring code. Generic rules to prevent the most common review comments — function length, naming, error handling, security, and…
Apply when designing database schemas, writing migrations, or reviewing table structure. Covers naming, keys, indexes, constraints, nullability, and migration…
Apply when diagnosing a bug, reproducing a failure, or performing root cause analysis. Covers systematic isolation, binary search, logging strategy, and…