skills/typescript-patterns/SKILL.md
Best practices for TypeScript types, interfaces, assertions, and type safety. Use when writing or reviewing TypeScript code.
npx skillsauth add adrianbrowning/agent-skills typescript-patternsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Best practices for types, interfaces, assertions, and type safety.
// ✅ Inferred return type
function calculateTotal(items: OrderItem[]) {
return items.reduce((sum, item) => sum + item.price, 0);
}
// ❌ Explicit return type
function calculateTotal(items: OrderItem[]): number {
return items.reduce((sum, item) => sum + item.price, 0);
}
Why: Inference catches implicit type coercion bugs.
Never hard cast from JSON.parse. Validate at runtime.
// ❌ Hard cast
const value: MyType = JSON.parse(message);
// ✅ Runtime assertion
function isMyType(value: unknown): value is MyType {
return typeof value === 'object' &&
value !== null &&
typeof (<MyType>value).prop === 'string';
}
const value = JSON.parse(message);
assert(isMyType(value), 'Invalid message format');
// Parameter: 'value' with 'unknown' type
// Always return boolean, never throw
function isStrategy(value: unknown): value is Strategy {
return typeof value === 'object' &&
value !== null &&
typeof (<Strategy>value).name === 'string';
}
// Use with assert
assert(isStrategy(value), 'Value is not a valid Strategy');
Always prefer types unless explicitly told otherwise.
// ✅ Type for object shapes
export type Product = {
id: string;
name: string;
price: number;
};
// ✅ Type for local function-scoped types
function validate(input: unknown) {
type Result = { errors: string[]; valid: boolean };
const output: Result = { errors: [], valid: true };
// ...
}
// ✅ Type for unions
type Status = 'pending' | 'active' | 'inactive';
// ❌ Interface (only use when explicitly requested)
export interface Product {
id: string;
name: string;
}
// ✅ Angle bracket syntax
const x = <number>y;
const config = <ConfigType>JSON.parse(json);
// ❌ 'as' syntax
const x = y as number;
Note: Only apply these when explicitly told to use interfaces instead of types.
I prefix or Data suffixOmit)// Adjective interfaces
interface Shippable {
shipping_address: string;
shipping_cost: number;
}
// Concrete interface
interface Order extends Shippable {
id: string;
total: number;
}
Never use enums. Use const objects with as const instead.
// ✅ Const object with as const
export const TenantModel = {
USER: 'user',
ORGANIZATION: 'organization',
EMPLOYER: 'employer'
} as const;
// Extract type from const
export type TenantModel = typeof TenantModel[keyof typeof TenantModel];
// ✅ Union type for simple cases
type Status = 'active' | 'inactive';
// ❌ Enum (never use)
export enum TenantModel {
USER = 'user',
ORGANIZATION = 'organization'
}
// Validate with Object.values
if (!Object.values(TenantModel).includes(model)) {
throw new Error('Invalid model');
}
// ✅ for...of loop
for (const item of items) {
processItem(item);
}
// ❌ forEach
items.forEach((item) => {
processItem(item);
});
Why: for...of works with break, continue, return, await, and has better debugging/stack traces.
Use map/filter/reduce for transformations, not side effects.
// ✅ Namespace imports
import * as mongodb from 'mongodb';
import * as Types from './types/index.js';
// ❌ Default imports
import MongoDB from 'mongodb';
types/ directories)ReturnType and Parameters to access private typesdevelopment
--- name: testing-best-practice description: A Skill for writing, reviewing, and refactoring tests using Artem-style principles: test intent over implementation, mock boundaries not internals, avoid flakiness, prefer integration tests, and use `using` for cleanup. --- # Testing Best Practice ## Instructions When the user asks for help with tests (writing new tests, improving existing ones, or defining testing standards), follow these rules: 1. **Test intent, not implementation** - Make te
development
Enforce Test-Driven Development with strict Red-Green-Refactor cycle using integration tests. Auto-triggers when implementing new features or functionality. Trigger phrases include "implement", "add feature", "build", "create functionality", or any request to add new behavior. Does NOT trigger for bug fixes, documentation, or configuration changes.
development
React Router v7 loader performance optimization techniques. Use when optimizing TTFB, eliminating waterfalls, consolidating database queries, or streaming secondary data in loaders. Triggers on "slow loaders", "optimize TTFB", "speed up React Router", "loader performance", or when loaders exceed 500ms response time.
development
Convert project plans to JSONL format (issues + dependencies). Use when users ask "convert plan to jsonl", "create jsonl from plan", "export plan as json" or "convert plan to taks", "create tasks from plan", "export plan as tasks".