Typescript best practices
TypeScript coding guidelines with dos and don'ts for type design and patterns. Use when writing, reviewing, or refactoring TypeScript code in projects with tsconfig.json or .ts/.tsx files. Trigger when the user asks to "review TypeScript code", "check my TS code", "write TypeScript", or when creating or modifying any .ts/.tsx file. Also applies when discussing type design, generics, naming conventions, interface vs type decisions, or TypeScript patterns. Boundary: not for JavaScript-only projects without TypeScript configuration.From its SKILL.md
npx -y skills add VdustR/vp-claude-code-marketplace --skill typescript-best-practicesAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
5.1 KB, ~1.1k tokens by cl100k_base, as published. Nobody here has run it
TypeScript Best Practices
Guidelines for writing clean, type-safe, and maintainable TypeScript code.
Note: If the repository has established code style conventions, follow those first. These guidelines serve as defaults.
Core Principles
- Type-First Design - Define types before implementation; minimize reliance on inference
- Interface for Structure - Use
interfacefor objects,typefor unions/mapped/conditional - Namespace for Type Organization - Group related types with namespaces (types only, not runtime)
- Generic Const for Strictness - Use
<const TConfig>for strict literal inference - Extract, Don't Redefine - Get types from existing definitions instead of duplicating
- Strictest Config - Use strictest tsconfig base; install
ts-resetfor saner built-in types
Quick Reference
interface vs type
| Use | When |
|---|---|
interface | Object structures, class contracts, extensible APIs |
type | Union types, mapped types, conditional types, tuples |
Naming Conventions
| Element | Convention | Example |
|---|---|---|
| Interface/Type | PascalCase | UserProfile, ResponseData |
| Generic parameters | T prefix | TUser, TConfig (never bare T, K, V) |
| Acronyms | First cap only | userId, ApiResponse (NOT userID, APIResponse) |
| Constants | UPPER_SNAKE | MAX_RETRY_COUNT |
| Variables/Functions | camelCase | getUserById, isActive |
Array Syntax
| DO | DON'T |
|---|---|
Array<TItem> | TItem[] |
ReadonlyArray<TItem> | readonly TItem[] |
Object Types
| Use Case | DO | DON'T |
|---|---|---|
| Empty object | Record<string, never> | {} |
| Any object (extends) | Record<string, any> | Record<string, unknown> |
| Any object (annotation) | Record<string, unknown> | Record<string, any> |
| Non-primitive | object | {} |
Assertions
| DO | DON'T |
|---|---|
| Zod/arktype for runtime validation | response as User |
satisfies for compile-time checks | value as unknown as Type |
Type guards (if ('prop' in obj)) | as any to silence errors |
| Explicit null checks | x! non-null assertion |
Function Declarations
// DO: Type on the const
const myFunction: myFunction.Type = (options) => {
// implementation
};
// DO: satisfies when namespace doesn't exist
const onClick = ((event) => {
// implementation
}) satisfies React.ComponentProps<'button'>['onClick'];
Type Extraction
// DO: Extract from existing definitions
type OnClick = React.ComponentProps<'button'>['onClick'];
type ItemIds = Array<Item['id']>;
type TimeoutType = NonNullable<typeof config['timeout']>;
// DON'T: Manually redefine types
type BadItemIds = Array<number>; // Won't update if Item.id changes
Summary Checklist
Before committing TypeScript code, verify:
- Used
interfacefor object types,typefor unions/mapped/conditional - No
asor!assertions — use Zod,satisfies, type guards, or explicit null checks - Branded types use Zod
.brand()or type-festTagged(not manual casting) - Naming follows conventions (PascalCase types,
Tprefix for generics,IdnotID) - Types extracted from existing definitions where possible
- Functions use namespace pattern for complex type organization
- Arrow functions for const declarations
- Complex generics have type tests
Reference Files
For detailed patterns and examples, see:
- type-patterns.md - Type syntax, assertions, namespace pattern, generics
- code-style.md - Safe array access, early return, avoid destructuring, avoid enum
- union-exhaustive.md - Discriminated unions + exhaustive handling (e.g., for state, events, API responses)
- branded-types.md - Nominal types for ID/unit safety (e.g., UserId vs OrderId)
- template-literals.md - String pattern types (e.g., event names, CSS values, route parameters)
- type-testing.md - Type-level testing with
*.test-d.tsfiles - setup.md - tsconfig, strict options, ts-reset configuration
Notes
- These guidelines complement, not replace, project-specific conventions
- When in doubt, prioritize readability and maintainability
- Runtime type validation (zod, arktype) is recommended for external data
- Avoid over-engineering types; simple is better than clever
What ships with it: 7 files
25.9 KB alongside SKILL.md
references/
- branded-types.md2.2 KB
- code-style.md5.0 KB
- setup.md2.0 KB
- template-literals.md1.5 KB
- type-patterns.md8.9 KB
- type-testing.md3.0 KB
- union-exhaustive.md3.2 KB