أفضل ممارسات TypeScript في مشاريع كبيرة

أفضل ممارسات TypeScript في مشاريع كبيرة

Ahmad BarishAhmad Barish
10 دقيقة للقراءة

دليل شامل لاستخدام TypeScript بفعالية في المشاريع الكبيرة مع أنماط التصميم والممارسات الموصى بها.

10 دقيقة للقراءة
📝813 كلمة
0 مشاهدة
# أفضل ممارسات TypeScript في مشاريع كبيرة TypeScript أصبح معياراً في تطوير JavaScript الحديث. في هذا المقال، سنغطي أفضل الممارسات للمشاريع الكبيرة. ## 1. الإعداد الصحيح للمشروع ### tsconfig.json محسّن: ```json { "compilerOptions": { "target": "ES2020", "module": "ESNext", "lib": ["ES2020", "DOM", "DOM.Iterable"], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "jsx": "react-jsx", "baseUrl": ".", "paths": { "@/*": ["src/*"], "@/components/*": ["src/components/*"], "@/utils/*": ["src/utils/*"] } }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] } ``` ## 2. أنواع البيانات (Types) المتقدمة ### Utility Types مخصصة: ```typescript // types/utils.ts type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>; type RequireAtLeastOne<T, Keys extends keyof T = keyof T> = Pick<T, Exclude<keyof T, Keys>> & { [K in Keys]-?: Required<Pick<T, K>> & Partial<Pick<T, K, K extends Keys ? K : never>> }[Keys]; type DeepPartial<T> = { [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P]; }; ``` ### Discriminated Unions للنماذج المعقدة: ```typescript type ApiResponse<T> = | { status: 'success'; data: T } | { status: 'error'; error: string } | { status: 'loading' }; function handleApiResponse<T>(response: ApiResponse<T>) { switch (response.status) { case 'success': console.log(response.data); // T break; case 'error': console.error(response.error); // string break; case 'loading': console.log('Loading...'); break; } } ``` ## 3. تصميم API قوي ### Builder Pattern للإعداد المعقد: ```typescript class QueryBuilder<T> { private filters: Partial<T>[] = []; private sorts: { field: keyof T; order: 'asc' | 'desc' }[] = []; private limit?: number; private offset?: number; where(filter: Partial<T>): this { this.filters.push(filter); return this; } orderBy(field: keyof T, order: 'asc' | 'desc' = 'asc'): this { this.sorts.push({ field, order }); return this; } take(limit: number): this { this.limit = limit; return this; } skip(offset: number): this { this.offset = offset; return this; } async execute(): Promise<T[]> { // تنفيذ الاستعلام return []; } } // الاستخدام const users = await new QueryBuilder<User>() .where({ active: true }) .where({ role: 'admin' }) .orderBy('createdAt', 'desc') .take(10) .execute(); ``` ## 4. إدارة الأخطاء بفعالية ### Error Boundaries مخصصة: ```typescript class AppErrorBoundary extends Component<PropsWithChildren, { hasError: boolean; error?: Error }> { constructor(props: PropsWithChildren) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error: Error) { return { hasError: true, error }; } componentDidCatch(error: Error, errorInfo: ErrorInfo) { // تسجيل الخطأ logError(error, errorInfo); } render() { if (this.state.hasError) { return <ErrorFallback error={this.state.error} />; } return this.props.children; } } ``` ### Result Type للعمليات غير المتزامنة: ```typescript type Result<T, E = Error> = | { success: true; data: T } | { success: false; error: E }; async function safeApiCall<T>(url: string): Promise<Result<T>> { try { const response = await fetch(url); if (!response.ok) { return { success: false, error: new Error(`HTTP ${response.status}`) }; } const data = await response.json(); return { success: true, data }; } catch (error) { return { success: false, error: error as Error }; } } // الاستخدام const result = await safeApiCall<User>('/api/user'); if (result.success) { console.log(result.data); } else { console.error(result.error); } ``` ## 5. أنماط التصميم مع TypeScript ### Strategy Pattern: ```typescript interface PaymentStrategy { pay(amount: number): Promise<PaymentResult>; } class CreditCardPayment implements PaymentStrategy { async pay(amount: number): Promise<PaymentResult> { // منطق الدفع بالبطاقة الائتمانية return { success: true, transactionId: '123' }; } } class PayPalPayment implements PaymentStrategy { async pay(amount: number): Promise<PaymentResult> { // منطق الدفع عبر PayPal return { success: true, transactionId: '456' }; } } class PaymentProcessor { constructor(private strategy: PaymentStrategy) {} async process(amount: number): Promise<PaymentResult> { return this.strategy.pay(amount); } setStrategy(strategy: PaymentStrategy) { this.strategy = strategy; } } ``` ### Dependency Injection Container: ```typescript class Container { private services = new Map<string, any>(); register<T>(token: string, factory: () => T): void { this.services.set(token, factory); } resolve<T>(token: string): T { const factory = this.services.get(token); if (!factory) { throw new Error(`Service ${token} not registered`); } return factory(); } } // الاستخدام const container = new Container(); container.register('Logger', () => new ConsoleLogger()); container.register('ApiService', () => new ApiService(container.resolve('Logger'))); const apiService = container.resolve<ApiService>('ApiService'); ``` ## 6. ملفات التعريف (Declaration Files) ### للمكتبات المخصصة: ```typescript // types/custom-library.d.ts declare module 'custom-library' { export interface Config { apiKey: string; timeout?: number; } export class Client { constructor(config: Config); get(endpoint: string): Promise<any>; post(endpoint: string, data: any): Promise<any>; } } ``` ## 7. اختبار TypeScript ### Testing Utilities: ```typescript // test/utils.ts export function createMock<T>(overrides: Partial<T> = {}): T { return overrides as T; } export function expectType<T>(value: T): void { // لا يفعل شيئاً في runtime، لكن يتحقق من النوع في compile time } // الاستخدام في الاختبارات describe('UserService', () => { it('should create user', async () => { const mockUser = createMock<User>({ id: 1, name: 'John Doe', email: 'john@example.com' }); expectType<User>(mockUser); // compile-time check const result = await userService.create(mockUser); expect(result).toBeDefined(); }); }); ``` ## 8. أدوات التطوير ### ESLint + Prettier مع TypeScript: ```json // .eslintrc.js module.exports = { extends: [ 'eslint:recommended', '@typescript-eslint/recommended', 'prettier' ], parser: '@typescript-eslint/parser', plugins: ['@typescript-eslint'], rules: { '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }], '@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/no-explicit-any': 'warn' } }; ``` ## خاتمة TypeScript في المشاريع الكبيرة يتطلب تخطيطاً وتنظيماً جيداً. ابدأ بإعداد قوي، ثم ركز على تصميم الأنواع والـ APIs. تذكر: الكود الجيد ليس فقط يعمل، بل يسهل فهمه وصيانته!