typescript
TypeScript type system, strict mode, and TS-specific patterns beyond JavaScript fundamentals. Invoke whenever task involves any interaction with TypeScript code — writing, reviewing, refactoring, debugging .ts/.tsx files, type definitions, generics, narrowing, tsconfig, or type-level programming.
What this skill does
# TypeScript
<prerequisite>
This skill extends the JavaScript skill. You must load `javascript` first — naming,
ternary operator rules, async patterns, and module conventions are defined there and
not duplicated here.
</prerequisite>
**Types encode intent. Let the compiler prove the rest.**
TypeScript's value is in catching bugs at compile time. Write types that express your domain; let inference handle the
obvious. Never fight the type system — if you need `as` or `any`, the types are wrong.
## References
| Topic | Reference | Contents |
| -------------------------------------------------- | --------------------------------------------------- | ---------------------------------------------------------------------------------- |
| Generics, utility types, type-level programming | [`${CLAUDE_SKILL_DIR}/references/generics.md`] | Utility type tables, conditional/mapped type examples, infer, template literals |
| Narrowing, type guards, discriminated unions | [`${CLAUDE_SKILL_DIR}/references/narrowing.md`] | typeof/instanceof/in examples, exhaustive switch, type predicates, assertion fns |
| tsconfig options, module resolution, project setup | [`${CLAUDE_SKILL_DIR}/references/configuration.md`] | Base/strict/module configs, library setup, compiler directives, project structure |
| Branded types, overloads, class patterns, enums | [`${CLAUDE_SKILL_DIR}/references/patterns.md`] | Interface vs type examples, assertion patterns, enum anti-patterns, callback types |
## Type Safety
- **`strict: true` always.** No exceptions. It enables `strictNullChecks`, `noImplicitAny`, `strictFunctionTypes`, and
other critical checks.
- **`unknown` over `any`.** Use `unknown` and narrow with type guards. `any` disables type checking entirely. Reserve
`any` for migration or test mocks only — document why.
- **No non-null assertions (`!`) without justification.** Prefer narrowing. If `!` is truly needed, add a comment
explaining why the value cannot be null.
- **No type assertions (`as`) for object literals.** Use type annotations (`: Foo`) instead — assertions hide
missing/extra property errors.
### `unknown` vs `any` Decision
- **Value from external source (API, JSON.parse, user input)** → `unknown`
- **Function accepts anything, passes through without touching** → `unknown`
- **Migrating JS to TS incrementally** → `any` (temporary, with comment)
- **Test mock that intentionally bypasses type checking** → `any` (with comment)
### The `{}` Type
`{}` means "any non-nullish value" — almost never what you want.
- **`unknown`** → Everything (null, undefined, primitives, objects)
- **`object`** → Non-primitive, non-null values
- **`{}`** → Any non-nullish value (primitives included)
- **`Record<string, unknown>`** → Objects with string keys
Prefer `unknown` for opaque values, `Record<string, unknown>` for dict-like objects, `object` when you need "any
non-primitive".
## Type Annotations
- **Omit trivially inferred types.** Don't annotate `const x: number = 5` or `const s: string = "hello"`. The compiler
infers these correctly.
- **Annotate complex return types.** When inference produces opaque or wide types, annotate explicitly for readability.
- **Annotate function signatures at API boundaries.** Exported functions and public methods should have explicit
parameter and return types.
- **Use `import type` for type-only imports.** Enforced by `verbatimModuleSyntax`. Use `export type` for type re-exports
— required for `isolatedModules`.
- **Annotate for precision with structural types.** Annotate at declaration so errors appear where the bug is, not at
distant call sites.
## Interfaces and Types
- **`interface` for object shapes.** Better error messages, IDE support, and performance.
- **`type` for everything else** — unions, intersections, tuples, function types, mapped/conditional types.
- **Decision rule:** Object shape with known properties? `interface`. Everything else? `type`. Pick one pattern per kind
and stay consistent within a project.
- **No empty interfaces.** Use a branded type or discriminated union as a marker.
- **No `namespace`.** Use ES modules. `namespace` is legacy.
- **No wrapper types.** `string` not `String`, `number` not `Number`.
- **Use interfaces for data shapes, not classes.** A class used purely as a data shape adds unnecessary overhead.
## Null Handling
- **Prefer optional `?` over `| undefined`** for fields and parameters. `| undefined` forces callers to pass `undefined`
explicitly.
- **Don't include `null`/`undefined` in type aliases.** Keep nullability at the use site:
`function getUser(): User | null` not `type MaybeUser = User | null`.
- **Null narrowing:** `!= null` checks both null and undefined (the one valid `==` use). `?.` for optional access. `??`
for defaults.
## Generics
- **Name type parameters descriptively** when meaning is non-obvious. `T` is fine for single-parameter generics; use
`TKey`, `TValue`, `TItem` for multiple parameters.
- **Constrain generics** with `extends` when possible. `<T extends string>` is better than `<T>` if `T` must be a
string.
- **Keep generic constraints tight** — `<T extends Record<string, unknown>>` is better than `<T extends object>` when
you need string keys.
- **Don't add unused type parameters.** Every generic must appear in the signature.
- **Avoid return-type-only generics.** If a generic appears only in the return type, it cannot be inferred and forces
callers to guess.
- **Let inference work.** Don't specify type arguments when the compiler can infer them: `identity("hello")` not
`identity<string>("hello")`.
- **Use type parameters in constraints:** `<T, K extends keyof T>` to relate parameters.
- **Generic parameter defaults:** `interface Container<T, U = T[]>` — omitted type args fall back to the default.
- **`NoInfer<T>`** (TS 5.4+) prevents a parameter from being an inference site — use when a parameter should be
constrained by other params, not drive inference.
### Utility Types
Prefer built-in utility types over hand-rolling equivalents. Key types: `Partial`, `Pick`, `Omit`, `Record`, `Exclude`,
`Extract`, `ReturnType`, `Parameters`, `Awaited`, `NoInfer`. Use explicit interfaces when the type represents a distinct
domain concept. See `${CLAUDE_SKILL_DIR}/references/generics.md` for the full catalog and usage guidance.
Conditional types (`T extends U ? X : Y`), mapped types (`{ [P in keyof T]: ... }`), and template literal types
(`` `${T}Changed` ``) are advanced tools — use for library code and framework types. See
`${CLAUDE_SKILL_DIR}/references/generics.md` for distributive behavior, `infer`, modifier removal, and key remapping.
### Complexity Budget
- **Simple** (`interface`, `type` alias, union) → Always — default choice
- **Moderate** (`Partial`, `Pick`, `Omit`, `Record`) → Well-known transformations
- **Advanced** (Conditional, mapped, template literal) → Library code, framework types
- **Expert** (Recursive types, complex `infer` chains) → Rarely — last resort
Stay at the lowest tier that solves your problem. If you can't explain what a type does in one sentence, it's too
complex — split it, simplify it, or use explicit interfaces.
## Narrowing
- **Prefer discriminated unions** for variant types. Add a `kind` or `type` literal field to each variant.
- **Use exhaustive switches.** Add `default: { const _exhaustive: never = value; return _exhaustive; }` to catch
unhandled variants at compile time.
- **Type predicates for reusable guards:** `function isFish(pet: Animal): pet is Fish`. Use when filtering arrays or in
multiple call sites.
- **Assertion functions:** `function assertIsError(value: unknown): asserts value is Error` — use for validation at
boundaries.
- **`typeof`, `instanceof`, `in`** — use JavaScript narrowing consRelated in Productivity
gitea-workflow
IncludedOrchestrate agile development workflows for Gitea repositories using the tea CLI. Use when working with Gitea-hosted repos and asking to 'run the workflow', 'continue working', 'what's next', 'complete the task cycle', 'start my day', 'end the sprint', 'implement the next task', or wanting guided step-by-step development assistance. Keywords: workflow, orchestrate, agile, task cycle, sprint, daily, implement, review, PR, standup, retrospective, gitea, tea.
microsoft-graph-gateway
IncludedRoute Microsoft Graph work in this workspace. Use when users want to read or write Outlook mail, calendar events, contacts, OneDrive or SharePoint files, Teams, Planner, To Do, users, groups, directory data, or arbitrary Microsoft Graph endpoints from VS Code. Prefer WorkIQ for common read scenarios. Use Microsoft Graph for write actions and gap-read scenarios that need exact Graph properties, filters, permissions, or endpoints.
copilotkit
IncludedUse when building with CopilotKit — setup, development, integrations, debugging, upgrading, or contributing. Routes to the appropriate specialized skill based on the task.
wordly-wisdom
IncludedProvides calibrated decision analysis using Charlie Munger-style multiple mental models, inversion, incentive mapping, circle-of-competence checks, misjudgment audits, second-order effects, and forecast updates. Use when the user asks for an oracle take, a hard call, a decision memo, a premortem, an outside view, a red-team, a sanity-check, what am I missing, think this through, or wants a strategy, hire, investment, plan, product, partnership, or major life choice analysed. Avoid for simple factual lookups or time-sensitive legal, medical, or market questions without fresh evidence.
swain-session
IncludedSession management and project status dashboard. Owns the full session lifecycle (start/work/close/resume), focus lane, bookmarks, worktree detection, and tab naming. Also serves as the project status dashboard — shows active epics, progress, actionable next steps, blocked items, tasks, GitHub issues, and recommendations. Worktree creation is deferred to swain-do task dispatch (SPEC-195). Triggers on: 'session', 'status', 'what's next', 'dashboard', 'overview', 'where are we', 'what should I work on', 'show me priorities', 'bookmark', 'focus on', 'session info'.
gandi
IncludedComprehensive Gandi domain registrar integration for domain and DNS management. Register and manage domains, create/update/delete DNS records (A, AAAA, CNAME, MX, TXT, SRV, and more), configure email forwarding and aliases, check SSL certificate status, create DNS snapshots for safe rollback, bulk update zone files, and monitor domain expiration. Supports multi-domain management, zone file import/export, and automated DNS backups. Includes both read-only and destructive operations with safety controls.