typescript-best-practices
4
总安装量
3
周安装量
#50530
全站排名
安装命令
npx skills add https://github.com/codelab614/agents-skills --skill typescript-best-practices
Agent 安装分布
claude-code
2
windsurf
1
opencode
1
weavefox
1
codex
1
Skill 文档
TypeScript Best Practices
When to Apply
Apply these rules when:
- Writing new TypeScript code
- Reviewing TypeScript code
- Refactoring JavaScript to TypeScript
- Fixing type errors
- Optimizing type definitions
Core Rules
1. Avoid any – Use Proper Types
Never use any unless absolutely necessary. Instead:
- Use
unknownfor truly unknown types - Use generics for flexible typing
- Use union types for multiple possibilities
// BAD
function parse(data: any): any { ... }
// GOOD
function parse<T>(data: unknown): T | null { ... }
2. Enable Strict Mode
Always use strict TypeScript configuration:
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"noImplicitReturns": true
}
}
3. Use Type Guards for Runtime Checks
// Type guard function
function isUser(value: unknown): value is User {
return (
typeof value === 'object' &&
value !== null &&
'id' in value &&
'name' in value
);
}
// Usage
if (isUser(data)) {
console.log(data.name); // TypeScript knows it's User
}
4. Prefer Interfaces for Objects, Types for Unions
// Use interface for object shapes
interface User {
id: string;
name: string;
email: string;
}
// Use type for unions and complex types
type Status = 'pending' | 'active' | 'inactive';
type Result<T> = { success: true; data: T } | { success: false; error: Error };
5. Use Readonly for Immutable Data
interface Config {
readonly apiUrl: string;
readonly timeout: number;
}
// Or use Readonly utility
type ImmutableUser = Readonly<User>;
6. Leverage Utility Types
// Partial - all properties optional
type UserUpdate = Partial<User>;
// Pick - select specific properties
type UserPreview = Pick<User, 'id' | 'name'>;
// Omit - exclude properties
type UserWithoutEmail = Omit<User, 'email'>;
// Record - typed object maps
type UserRoles = Record<string, 'admin' | 'user' | 'guest'>;
7. Type-Safe Error Handling
// Define error types
class AppError extends Error {
constructor(
message: string,
public code: string,
public statusCode: number
) {
super(message);
this.name = 'AppError';
}
}
// Result pattern
type Result<T, E = Error> =
| { ok: true; value: T }
| { ok: false; error: E };
function divide(a: number, b: number): Result<number> {
if (b === 0) {
return { ok: false, error: new Error('Division by zero') };
}
return { ok: true, value: a / b };
}
8. Use Generics for Reusable Code
// Generic function
function first<T>(array: T[]): T | undefined {
return array[0];
}
// Generic with constraints
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
// Generic interface
interface Repository<T> {
find(id: string): Promise<T | null>;
save(entity: T): Promise<T>;
delete(id: string): Promise<boolean>;
}
9. Const Assertions for Literal Types
// Without as const - type is string[]
const colors = ['red', 'green', 'blue'];
// With as const - type is readonly ['red', 'green', 'blue']
const colors = ['red', 'green', 'blue'] as const;
type Color = typeof colors[number]; // 'red' | 'green' | 'blue'
10. Discriminated Unions for State
type AsyncState<T> =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: T }
| { status: 'error'; error: Error };
function render<T>(state: AsyncState<T>) {
switch (state.status) {
case 'idle':
return 'Ready';
case 'loading':
return 'Loading...';
case 'success':
return `Data: ${state.data}`; // TypeScript knows data exists
case 'error':
return `Error: ${state.error.message}`; // TypeScript knows error exists
}
}
Naming Conventions
| Type | Convention | Example |
|---|---|---|
| Interface | PascalCase | UserProfile |
| Type alias | PascalCase | RequestConfig |
| Enum | PascalCase | HttpStatus |
| Enum member | UPPER_SNAKE or PascalCase | HTTP_OK or HttpOk |
| Generic | Single uppercase letter or descriptive | T, TData, TResponse |
| Function | camelCase | getUserById |
| Variable | camelCase | userList |
| Constant | UPPER_SNAKE or camelCase | MAX_RETRIES or maxRetries |
Anti-Patterns to Avoid
- Don’t use
anyas escape hatch – Useunknownand narrow the type - Don’t use
!non-null assertion – Check for null/undefined properly - Don’t use
@ts-ignore– Fix the type error instead - Don’t export everything – Only export what’s needed
- Don’t use
Functiontype – Use specific function signatures