typescript-patterns
4
总安装量
2
周安装量
#51463
全站排名
安装命令
npx skills add https://github.com/adrianbrowning/agent-skills --skill typescript-patterns
Agent 安装分布
claude-code
2
replit
1
opencode
1
codex
1
github-copilot
1
Skill 文档
TypeScript Patterns Skill
Best practices for types, interfaces, assertions, and type safety.
Type Inference Over Explicit Returns
// â
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.
Runtime Type Assertions
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');
Type Assertion Functions
// 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');
Types vs Interfaces
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;
}
Casting Syntax
// â
Angle bracket syntax
const x = <number>y;
const config = <ConfigType>JSON.parse(json);
// â 'as' syntax
const x = y as number;
Interface Conventions (Only When Explicitly Using Interfaces)
Note: Only apply these when explicitly told to use interfaces instead of types.
- No
Iprefix orDatasuffix - Properties in alphabetical order
- Think of interfaces as nouns or adjectives (Shippable, Refundable)
- When extending, inherit ALL properties (no
Omit)
// Adjective interfaces
interface Shippable {
shipping_address: string;
shipping_cost: number;
}
// Concrete interface
interface Order extends Shippable {
id: string;
total: number;
}
Constants Over Enums
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');
}
Iteration
// â
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.
Import Style
// â
Namespace imports
import * as mongodb from 'mongodb';
import * as Types from './types/index.js';
// â Default imports
import MongoDB from 'mongodb';
Organization
- Keep types with related code (not in
types/directories) - Only export types that are part of public API
- Use
ReturnTypeandParametersto access private types