Loading...
Loading...
Best practices for TypeScript types, interfaces, assertions, and type safety. Use when writing or reviewing TypeScript code.
npx skill4agent add adrianbrowning/agent-skills typescript-patterns// ✅ 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);
}JSON.parse// ❌ 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');// ✅ 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;IDataOmit// Adjective interfaces
interface Shippable {
shipping_address: string;
shipping_cost: number;
}
// Concrete interface
interface Order extends Shippable {
id: string;
total: number;
}as const// ✅ 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);
});for...ofbreakcontinuereturnawaitmapfilterreduce// ✅ Namespace imports
import * as mongodb from 'mongodb';
import * as Types from './types/index.js';
// ❌ Default imports
import MongoDB from 'mongodb';types/ReturnTypeParameters