أفضل ممارسات TypeScript في مشاريع كبيرة
دليل شامل لاستخدام 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.
تذكر: الكود الجيد ليس فقط يعمل، بل يسهل فهمه وصيانته!