| name | ts-coding-standards |
| description | Use when writing, reviewing, or refactoring TypeScript code. Provides type safety patterns, error handling, project layout, and async programming guidelines. |
| allowed-tools | Read, Grep, Glob |
TypeScript Coding Standards
This skill provides modern TypeScript coding guidelines and best practices for this project.
When to Apply
Apply these standards when:
- Writing new TypeScript code
- Reviewing or refactoring existing TypeScript code
- Designing module APIs and interfaces
- Implementing error handling strategies
Core Principles
- Type Safety Over Convenience - Never sacrifice type safety for shorter code
- Explicit Over Implicit - Make types and intentions clear
- Simple Over Clever - Prefer readable code over clever abstractions
- Fail Fast - Catch errors at compile time, not runtime
Quick Reference
Must-Use Patterns
| Pattern | Use Case |
|---|
| Discriminated Unions | State machines, API responses, Result types |
| Branded Types | IDs, emails, validated strings |
readonly | Data that should not mutate |
unknown in catch | Safe error handling |
| Explicit undefined checks | Array/object indexed access |
Must-Avoid Anti-Patterns
| Anti-Pattern | Alternative |
|---|
any type | unknown with type guards |
| Throwing exceptions for control flow | Result type pattern |
| Optional chaining without null check | Explicit narrowing |
| Deep folder nesting (>3 levels) | Flat, feature-based structure |
Implicit undefined in optional props | Explicit T | undefined |
Ambiguous variable names (store, id, data) | Self-descriptive names (sessionStore, sessionId, userData) |
Single-character lambda params (x => x.name) | Descriptive params (session => session.name) |
Naming Conventions: Self-Descriptive Variable Names
RULE: All variable, parameter, and property names MUST be self-descriptive. Avoid short, ambiguous names that require surrounding context to understand. Code should read like prose -- a reader should understand what a variable holds without looking at its declaration or surrounding code.
Prohibited Patterns
store.get(id);
const res = await fetch(url);
const val = map.get(key);
items.filter(x => x.active);
data.forEach(d => process(d));
const cb = () => { };
sessionStore.get(sessionId);
const apiResponse = await fetch(endpointUrl);
const configValue = configMap.get(configKey);
sessions.filter(session => session.active);
diffEntries.forEach(diffEntry => processDiffEntry(diffEntry));
const onSessionExpired = () => { };
Single-Character Variables Are Prohibited
Even in lambda expressions, arrow functions, and short callbacks, single-character variable names (x, e, d, v, i, k) are prohibited. Use descriptive names that convey what the value represents.
users.map(u => u.name);
entries.filter(e => e.isValid);
Object.entries(obj).forEach(([k, v]) => console.log(k, v));
for (let i = 0; i < items.length; i++) { }
users.map(user => user.name);
entries.filter(entry => entry.isValid);
Object.entries(configMap).forEach(([configKey, configValue]) => console.log(configKey, configValue));
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) { }
General Guidelines
- Variable names should describe WHAT, not HOW:
sessionStore (what it stores) over store (generic)
- Parameters should describe the domain concept:
sessionId over id, filePath over path
- Collections should hint at their contents:
sessions over items, diffEntries over data
- Callbacks should describe their trigger:
onSessionExpired over cb, handleFileChange over fn
Detailed Guidelines
For comprehensive guidance, see:
tsconfig.json Strict Mode
This project uses maximum TypeScript strictness. Ensure your code compiles with:
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noPropertyAccessFromIndexSignature": true,
"noFallthroughCasesInSwitch": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"noUnusedParameters": true
}
}
References