refactoring-typescript
TypeScript refactoring: SOLID principles, DRY, type safety improvements, and eliminating code smells
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
TypeScript refactoring: SOLID principles, DRY, type safety improvements, and eliminating code smells
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Architecture decisions: layering, design patterns, microservices trade-offs, and domain-driven design
Python architecture: PEP-8, type hints, clean layering, dependency injection, and testing strategy
General code review process: priority ordering, what to block on, how to give actionable feedback
Python data science: notebook structure, data validation, reproducibility, and model documentation
Git workflow: branch naming, conventional commits, PR conventions, and merge strategies
Security checklist: OWASP top 10, secret scanning, input validation, and auth patterns
| name | refactoring-typescript |
| description | TypeScript refactoring: SOLID principles, DRY, type safety improvements, and eliminating code smells |
tsc --noEmit and eslint after each change.any with proper types or unknown + type guard.strict: true in tsconfig.json if not set.interface for object shapes; type for unions and intersections.readonly arrays and properties when data should not be mutated.// Before
function process(data: any) { ... }
// After
function process(data: unknown) {
if (!isOrderData(data)) throw new TypeError('Invalid order data');
...
}
// Prefer discriminated unions over boolean flags
type Result =
| { status: 'ok'; value: string }
| { status: 'error'; message: string };
is, has, can, should.url, id, ctx).// Before
const d = users.filter(u => u.a);
// After
const activeUsers = users.filter(user => user.isActive);
if/else chains that grow over time.| Smell | Fix |
|---|---|
| Long parameter list (4+) | Extract to typed options object |
| Deep nesting | Early returns / guard clauses |
| Magic numbers/strings | Named constants or enums |
| Copy-pasted logic | Extract to named function or generic utility |
| Large file (300+ lines) | Split into focused modules |
| Boolean parameter | Two functions, or discriminated union |
| Comments explaining what | Rename so it's self-evident |
| Mutable shared state | Encapsulate behind a function; return new values |
| Callback pyramid | Async/await with named steps |
// Before — deep nesting
function processOrder(order: Order) {
if (order) {
if (order.items.length > 0) {
if (order.status === 'pending') {
// actual logic...
}
}
}
}
// After — guard clauses
function processOrder(order: Order) {
if (!order) return;
if (order.items.length === 0) return;
if (order.status !== 'pending') return;
// actual logic...
}
// Before — inline logic that hides intent
const total = items.reduce((sum, item) => {
const discounted = item.price * (1 - item.discountRate);
return sum + discounted * item.quantity;
}, 0);
// After — named helpers reveal intent
const lineTotal = (item: Item) => item.price * (1 - item.discountRate) * item.quantity;
const total = items.reduce((sum, item) => sum + lineTotal(item), 0);
// Before
function createUser(name: string, age: number, role: string, active: boolean) { ... }
// After
interface CreateUserOptions {
name: string;
age: number;
role: string;
active: boolean;
}
function createUser(options: CreateUserOptions) { ... }
// Before — callback pyramid / chained .then
fetchUser(id)
.then(user => fetchOrders(user.id)
.then(orders => fetchInvoices(orders[0].id)
.then(invoices => process(user, orders, invoices))));
// After — sequential async/await
async function loadUserData(id: string) {
const user = await fetchUser(id);
const orders = await fetchOrders(user.id);
const invoices = await fetchInvoices(orders[0].id);
return process(user, orders, invoices);
}
// Before — growing switch that requires editing this function for each new type
function calculateShipping(method: string, weight: number): number {
if (method === 'standard') return weight * 0.5;
if (method === 'express') return weight * 1.2;
if (method === 'overnight') return weight * 2.5;
throw new Error('Unknown method');
}
// After — register new strategies without touching existing code
type ShippingStrategy = (weight: number) => number;
const shippingStrategies: Record<string, ShippingStrategy> = {
standard: w => w * 0.5,
express: w => w * 1.2,
overnight: w => w * 2.5,
};
function calculateShipping(method: string, weight: number): number {
const strategy = shippingStrategies[method];
if (!strategy) throw new Error(`Unknown shipping method: ${method}`);
return strategy(weight);
}
// removed comments.tsc --noEmit and your linter's no-unused-vars / @typescript-eslint/no-unused-vars to surface dead code automatically.