جاري التحميل...
جاري التحميل...
تطبيق كامل باستخدام TypeScript
في هذا المشروع الأخير، سندمج كل ما تعلمته عن TypeScript لبناء تطبيق إدارة المهام كامل مع Next.js.
ابدأ بتعريف جميع الأنواع التي يحتاجها تطبيقك:
interface Task {
id: string;
title: string;
description: string;
status: 'todo' | 'in-progress' | 'done';
priority: 'low' | 'medium' | 'high';
createdAt: Date;
}
type TaskAction =
| { type: 'ADD'; payload: Task }
| { type: 'UPDATE'; payload: { id: string; updates: Partial<Task> } }
| { type: 'DELETE'; payload: { id: string } };ابنِ مكونات قابلة لإعادة الاستخدام مع تعريفات نوع صارمة:
استخدم useReducer مع أحداث مكتوبة بنوع لإدارة حالة متوقعة:
function taskReducer(state: Task[], action: TaskAction): Task[] {
switch (action.type) {
case 'ADD':
return [...state, action.payload];
case 'UPDATE':
return state.map(task =>
task.id === action.payload.id
? { ...task, ...action.payload.updates }
: task
);
case 'DELETE':
return state.filter(task => task.id !== action.payload.id);
default:
return state;
}
}استخدم TypeScript لإنشاء دوال تحقق آمنة النوع:
function validateTask(task: Partial<Task>): string[] {
const errors: string[] = [];
if (!task.title || task.title.length < 3) {
errors.push('يجب أن يكون العنوان 3 أحرف على الأقل');
}
if (!task.description) {
errors.push('الوصف مطلوب');
}
return errors;
}أي نمط يُستخدم لإجراءات المهام (ADD، UPDATE، DELETE)؟
ما هي فائدة استخدام useReducer مع TypeScript؟
ماذا يعني Partial<Task>؟
أضف ميزات: تصفية المهام حسب الأولوية، إعادة ترتيب بالسحب والإفلات، حفظ التخزين المحلي، وتبديل الوضع الداكن.
الحل:
// === 1. نظام التعليقات ===
interface Comment {
readonly id: string;
taskId: TaskId;
authorId: UserId;
content: string;
createdAt: Date;
}
// === 2. نظام التصفية المتقدم ===
async function searchTasks(
criteria: TaskSearchCriteria
): Promise<Task[]> {
const tasks = await taskRepo.getAll();
return tasks.filter((task) => {
if (criteria.status && !criteria.status.includes(task.status))
return false;
if (criteria.priority && !criteria.priority.includes(task.priority))
return false;
if (criteria.assignedTo && task.assignedTo !== criteria.assignedTo)
return false;
if (criteria.tags && !criteria.tags.some((t) => task.tags.includes(t)))
return false;
if (criteria.query) {
const q = criteria.query.toLowerCase();
if (!task.title.toLowerCase().includes(q) &&
!task.description.toLowerCase().includes(q))
return false;
}
if (criteria.dueBefore && task.dueDate && task.dueDate > criteria.dueBefore)
return false;
if (criteria.dueAfter && task.dueDate && task.dueDate < criteria.dueAfter)
return false;
return true;
});
}
// === 3. نظام الترتيب ===
function sortTasks(
tasks: Task[],
options: TaskSortOptions
): Task[] {
return [...tasks].sort((a, b) => {
const aVal = a[options.field];
const bVal = b[options.field];
if (aVal < bVal) return options.direction === "asc" ? -1 : 1;
if (aVal > bVal) return options.direction === "asc" ? 1 : -1;
return 0;
});
}
// === 4. إحصائيات الإنتاجية ===
async function getUserProductivity(userId: UserId): Promise<number> {
const tasks = await taskRepo.getAll();
const completed = tasks.filter(
(t) => t.assignedTo === userId && t.status === "done"
);
return completed.length;
}
// === 5. نظام الإشعارات ===
type Notification =
| { type: "email"; to: EmailAddress; subject: string; body: string }
| { type: "push"; deviceToken: string; title: string; message: string }
| { type: "in_app"; userId: UserId; message: string; link?: string };
function sendNotification(notification: Notification): void {
switch (notification.type) {
case "email":
console.log(`📧 إرسال بريد إلى ${notification.to}: ${notification.subject}`);
break;
case "push":
console.log(`📱 إشعار push: ${notification.title}`);
break;
case "in_app":
console.log(`🔔 إشعار داخل التطبيق: ${notification.message}`);
break;
}
}الدرس 1: مقدمة:
الدرس 2: الأنواع الأساسية:
الدرس 3: الواجهات:
الدرس 4: العامة:
الدرس 5: React:
الدرس 6: المشروع:
كيف تُصمم مشروع TypeScript كامل؟
الإجابة:
ابدأ بالـ types أولاً، ثم الدوال، ثم الاختبارات.
استخدم type-safe API
عرّف types للـ API responses في ملف منفصل