Idiomatic TypeScript patterns for clean, maintainable code.
Scanned 9/8/2026
Install to Claude Code
npx -y skills add ngxtm/devkit --skill best-practices --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Best Practices?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/ngxtm-best-practices-a183163f)More formats (shields.io, HTML) on the badges page.
---
name: TypeScript Best Practices
description: Idiomatic TypeScript patterns for clean, maintainable code.
metadata:
labels: [typescript, best-practices, idioms, conventions]
triggers:
files: ['**/*.ts', '**/*.tsx']
keywords: [class, function, module, import, export, async, promise]
---
# TypeScript Best Practices
## **Priority: P1 (OPERATIONAL)**
Idiomatic patterns for writing clean, maintainable TypeScript code.
## Implementation Guidelines
- **Naming Conventions**:
- PascalCase for classes, interfaces, types, enums
- camelCase for variables, functions, methods, parameters
- UPPER_SNAKE_CASE for constants
- Prefix interfaces with `I` only when necessary for disambiguation
- **Functions**:
- Prefer arrow functions for callbacks and short functions
- Use regular functions for methods and exported functions
- Always specify return types for public APIs
- **Modules**:
- One export per file for major components/classes
- Use named exports over default exports for better refactoring
- Organize imports: external -> internal -> relative
- **Async/Await**:
- Prefer `async/await` over raw Promises
- Always handle errors with try/catch in async functions
- Use `Promise.all()` for parallel operations
- **Classes**:
- Use `private`/`protected`/`public` modifiers explicitly
- Prefer composition over inheritance
- Use `readonly` for properties that don't change after construction
- **Exhaustiveness Checking**: Use `never` type in `switch` cases.
- **Assertion Functions**: Use `asserts` for runtime type validation.
- **Optional Properties**: Use `?:`, not `| undefined`.
- **Type Imports**: Use `import type` for tree-shaking.
## Anti-Patterns
- **No Default Exports**: Use named exports.
- **No Implicit Returns**: Specify return types.
- **No Unused Variables**: Enable `noUnusedLocals`.
- **No `require`**: Use ES6 `import`.
- **No Empty Interfaces**: Use `type` or non-empty interface.
## Code
````typescript
// Named Export + Immutable Interface
export interface User {
readonly id: string;
name: string;
}
// Exhaustive Check
function getStatus(s: 'ok' | 'fail') {
switch (s) {
case 'ok': return 'OK';
case 'fail': return 'Fail';
default: const _chk: never = s; return _chk;
}
}
// Assertion
function assertDefined<T>(val: T): asserts val is NonNullable<T> {
if (val == null) throw new Error("Defined expected");
}
``` private readonly repository: UserRepository;
constructor(repository: UserRepository) {
this.repository = repository;
}
async getUser(id: string): Promise<UserProfile> {
try {
return await this.repository.findById(id);
} catch (error) {
throw new Error(`Failed to get user: ${error.message}`);
}
}
}
// Organize imports
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { UserRepository } from '@/repositories/user.repository';
import { Logger } from '@/utils/logger';
// Type-only imports
import type { Request, Response } from 'express';
````
## Reference & Examples
For project structure and module organization:
See [references/REFERENCE.md](references/REFERENCE.md).
## Related Topics
language | tooling | security
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!