typescript
$
npx mdskill add EpicenterHQ/epicenter/typescriptEnforces TypeScript conventions for type definitions and code structure
- Helps decide when to derive, import, or declare new types
- Applies rules for naming, ownership, and runtime schema patterns
- Analyzes type usage and enforces clarity in contracts and interfaces
- Guides developers in organizing and reviewing TypeScript files
SKILL.md
.github/skills/typescriptView on GitHub ↗
---
name: typescript
description: 'TypeScript project conventions: derived types, type placement, acronym casing, imports, generics, factories, and runtime schema patterns. Use when editing `.ts` files, defining exported types, reviewing type names, or organizing type tests.'
metadata:
author: epicenter
version: '2.0'
---
# TypeScript Guidelines
Use this skill for project-wide TypeScript conventions before loading narrower skills such as `arktype`, `typebox`, `testing`, or `method-shorthand-jsdoc`.
## When To Apply This Skill
Use this skill when you need to:
- Write or refactor TypeScript with Epicenter naming and style conventions.
- Decide whether to derive, import, or declare a type.
- Review type ownership, copied shapes, factory return types, brands, casts, and generic names.
- Choose clear value-mapping and control-flow patterns for unions and discriminated values.
- Organize type tests, runtime schemas, or factory-focused refactors.
## Core Rules
- Try to derive or import a type before declaring a new named type. New named types must earn their place as a real contract, protocol vocabulary, discriminated result union, capability port, or multi-implementation shape.
- Treat local shape copies as boundary smells. Prefer the owning runtime type, schema inference, factory return type, function signature, or a caller-owned capability function.
- Use `type`, not `interface`.
- Use `readonly` only for arrays and maps, unless matching an upstream type exactly.
- Treat acronyms as normal words in camelCase: `parseUrl`, `defineKv`, `readJson`, `customerId`.
- Use `.js` extensions in relative imports. Do not use extensionless or `.ts` relative imports.
- Export symbols at their declarations. Reserve `export { ... } from ...` for barrel files.
- Prefer factory functions over classes. Let closure position communicate private vs public API.
- Use descriptive generic names with a `T` prefix, such as `TSchema`, `TDefs`, and `TKey`.
- Destructure options in the function signature when the object is a configuration bag. Keep a named value only when it is the domain object being transformed or forwarded.
- Let TypeScript infer private and inner return types. Annotate exported APIs only when useful for clarity or to break circular inference.
- If an exported type is exactly the object returned by a `create*` factory, derive it with `ReturnType<typeof createThing>`. Put useful annotations on returned members instead of duplicating the object shape.
- Use a `Symbol` brand when identity means a specific factory output, not a coincidental shape probe.
- Avoid `as any`. Use `unknown`, validation, brands, or narrower helpers instead.
- Prefer optional chaining over `in` checks or truthiness when checking optional properties.
- Use `is`, `has`, or `can` prefixes for booleans that answer a question.
- Prefer `switch` over `if/else` for repeated equality comparisons against the same value. Use `default: value satisfies never` for exhaustiveness when needed.
- Prefer `Record` lookup tables over nested ternaries for finite value mappings.
- Compose typed errors bottom-up. Do not filter a broad upstream error union at the boundary.
- Question silent fallbacks that hide invalid state. Preserve round-trip invariants when parsing and serializing.
## Reference Map
- [Project conventions](references/project-conventions.md): detailed examples for derived types, local shape copies, imports, barrels, factories, generics, destructuring, and factory return types.
- [Type safety and control flow](references/type-safety-and-control-flow.md): identity brands, casts, optional properties, boolean naming, switches, record lookups, error composition, fallback smells, and round-trip invariants.
- [Type organization](references/type-organization.md): `types.ts` location, co-location rules, inline-vs-extract hop test, options and ID naming.
- [Factory patterns](references/factory-patterns.md): factory-focused refactors, parameter destructuring, and coupled state extraction.
- [Runtime schema patterns](references/runtime-schema-patterns.md): arktype, branded IDs, optional property syntax, and workspace table IDs.
- [Testing patterns](references/testing-patterns.md): inline single-use setup and source-shadowing tests.
- [Advanced TypeScript features](references/advanced-typescript-features.md): iterator helpers and const generic array inference.
More from EpicenterHQ/epicenter
- agent-goalWrite `/goal` prompts for long-running agent work in Codex or Claude Code. Use for slash goal, agent goal, durable objective, autonomous coding run.
- approachability-auditReview code as a new TypeScript developer. Use when code feels indirect, clever, hard to follow, or needs a pass on abstractions, names, first-read clarity.
- arktypeArktype: runtime validation, discriminated unions with .merge()/.or(), spread keys. Use when mentioning arktype, type(), union types, command/event schemas.
- attach-primitiveContract and invariants for `attach*` composition primitives in `packages/workspace` (side-effectful building blocks like attachIndexedDb, attachSqlite, attachBroadcastChannel, attachEncryption, attachTable, openCollaboration), and when to use `create*` (pure construction) instead. Use when writing or reviewing an `attach*` or `create*` function, naming a new workspace primitive, composing inside a workspace builder, or deciding whether a primitive registers listeners at call time.
- authEpicenter auth packages: `@epicenter/auth`, `@epicenter/auth-svelte`, OAuth sessions, identity state, auth-owned fetch/WebSocket, and workspace lifecycle binding. Use when editing Epicenter auth clients, session state, hosted sign-in, or auth/workspace integration.
- autumnAutumn billing in Epicenter: `autumn.config.ts`, `autumn-js` credit checks, `atmn` CLI, plan gates, and metered AI usage. Use when changing billing, pricing, credits, plan access, refunds, or usage events.
- better-auth-best-practicesBetter Auth server/client setup: `auth.ts`, generated schema, DB adapters, sessions, cookies, env vars, and plugins. Use when mentioning Better Auth, betterauth, auth handlers, OAuth, email/password, or session configuration.
- better-auth-security-best-practicesBetter Auth security hardening: rate limits, secrets, CSRF, trusted origins, cookies, sessions, OAuth tokens, and audit logging. Use when reviewing auth security, brute-force protection, token handling, or deployment safety.
- change-proposalPresent proposed code changes visually before implementing. Use when: "show me options", "compare approaches", "what should we do", or when changes need before/after comparison.
- claude-code-consultUse this skill when the user asks to consult Claude, ask Claude Code, get another model's take, run a taste check, find cleaner options, or prepare a Claude prompt. Create a bounded second-opinion prompt or run a read-only Claude Code consult, then verify Claude's claims against local files.