# Typescript Best Practices

> TypeScript/Node.js best practices. Use when writing or reviewing TypeScript code. Covers type safety, async patterns, and error handling. Use when this capability is needed.

- Skill: `tomevault-io/typescript-best-practices-5` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/typescript-best-practices-5`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/typescript-best-practices-5/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/typescript-best-practices-5

---


# TypeScript Best Practices

## Code Style

| Rule | Guideline |
|------|-----------|
| Formatter | Prettier |
| Linter | ESLint + `@typescript-eslint` |
| Strict mode | `strict: true` in tsconfig |

## Type Safety

| Rule | Guideline |
|------|-----------|
| Avoid `any` | Use `unknown` + narrowing |
| Type guards | Custom predicates |
| Discriminated unions | For variants |

```typescript
type Result<T> = { success: true; data: T } | { success: false; error: Error };

function isUser(v: unknown): v is User {
  return typeof v === 'object' && v !== null && 'id' in v;
}
```

## Error Handling

```typescript
class ApiError extends Error {
  constructor(message: string, public status: number) {
    super(message);
    this.name = 'ApiError';
  }
}

async function fetchUser(id: string): Promise<User> {
  const res = await fetch(`/api/users/${id}`);
  if (!res.ok) throw new ApiError('Failed', res.status);
  return res.json();
}
```

## Project Structure

```
src/{index.ts, types/, services/, utils/}
tests/
package.json, tsconfig.json
```

## Async Patterns

| Pattern | Usage |
|---------|-------|
| `Promise.all` | Parallel operations |
| `AbortController` | Cancellation |

```typescript
const [user, settings] = await Promise.all([fetchUser(id), fetchSettings(id)]);
```

## Anti-Patterns

| Avoid | Use Instead |
|-------|-------------|
| `as` assertions | Type guards |
| `!` non-null | `?.` and `??` |
| `any` | `unknown` + narrowing |

```typescript
// Bad: data as User, user!.name
// Good:
if (isUser(data)) { /* data is User */ }
const name = user?.name ?? 'Unknown';
```

## Testing (Vitest)

```typescript
describe('Service', () => {
  it('should create', async () => {
    const mock = { save: vi.fn().mockResolvedValue({ id: '1' }) };
    const result = await new Service(mock).create({ name: 'Test' });
    expect(result.id).toBe('1');
  });
});
```

---
> Converted and distributed by [TomeVault](https://tomevault.io/claim/Taoidle) — claim your Tome and manage your conversions.
<!-- tomevault:4.0:skill_md:2026-04-16 -->

