نمذجة آلات الحالات
مثّلوا الحالات المحدودة باستخدام الاتحادات المميّزة
نمذجة آلات الحالات درس مجاني في TypeScript Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في TypeScript Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة TypeScript Academy 4 دروس في المجموع.
تمثيل الحالات كاتحاد مميّز
تتضمن واجهات المستخدم والتدفقات غير المتزامنة حالات متميزة: الخمول، والتحميل، والنجاح، والخطأ. وتتيح نمذجتها كاتحاد مميّز أن تحمل كل حالة البيانات التي تحتاج إليها بالضبط.
type State =
| { status: "idle" }
| { status: "loading" }
| { status: "success"; data: string }
| { status: "error"; message: string };
const s: State = { status: "idle" };
console.log(s.status);البيانات الخاصة بكل حالة
تحتوي حالة success وحدها على data، وتحتوي حالة error وحدها على message. أما حالتا الخمول والتحميل فلا تحملان بيانات إضافية، مما يمنع تسرّب البيانات القديمة بين الحالات.
type State =
| { status: "idle" }
| { status: "loading" }
| { status: "success"; data: number[] }
| { status: "error"; message: string };
const ok: State = { status: "success", data: [1, 2, 3] };
console.log(ok.status, "data" in ok ? ok.data : null);عرض كل حالة
يمكن لدالة تستخدم switch مع status عرض الناتج الصحيح لكل حالة، مع إتاحة حقول الأعضاء فقط في المواضع التي توجد فيها.
type State =
| { status: "idle" }
| { status: "loading" }
| { status: "success"; data: string }
| { status: "error"; message: string };
function view(s: State): string {
switch (s.status) {
case "idle": return "Ready";
case "loading": return "Loading...";
case "success": return "Got: " + s.data;
case "error": return "Failed: " + s.message;
}
}
console.log(view({ status: "success", data: "users" }));تعريف الانتقالات
تنتقل آلة الحالات بين الحالات عبر انتقالات. وتأخذ دالة الانتقال الحالة الحالية وحدثًا، ثم تُرجع الحالة التالية.
type State =
| { status: "idle" }
| { status: "loading" }
| { status: "success"; data: string }
| { status: "error"; message: string };
function start(s: State): State {
if (s.status === "idle") return { status: "loading" };
return s;
}
console.log(start({ status: "idle" }).status);نمذجة الأحداث أيضًا
يمكن أن تكون الأحداث نفسها اتحادًا مميّزًا. ويؤدي كل نوع من الأحداث إلى انتقال محدد.
type Event =
| { type: "FETCH" }
| { type: "RESOLVE"; data: string }
| { type: "REJECT"; message: string };
const e: Event = { type: "RESOLVE", data: "ok" };
console.log(e.type);دالة انتقال كاملة
ادمج اتحادي الحالة والحدث في مخفّض واحد. ويضمن استخدام switch مع كليهما أن يكون كل انتقال صريحًا وآمنًا من ناحية الأنواع.
type State =
| { status: "idle" }
| { status: "loading" }
| { status: "success"; data: string }
| { status: "error"; message: string };
type Event =
| { type: "FETCH" }
| { type: "RESOLVE"; data: string }
| { type: "REJECT"; message: string };
function reduce(s: State, e: Event): State {
if (e.type === "FETCH") return { status: "loading" };
if (e.type === "RESOLVE") return { status: "success", data: e.data };
return { status: "error", message: e.message };
}
console.log(reduce({ status: "idle" }, { type: "FETCH" }).status);الحالات غير القانونية غير قابلة للتمثيل
لا يمكنك امتلاك data وerror message في الوقت نفسه. إذ يمنع تصميم الاتحاد الحالات المتناقضة بحكم بنيته.
type State =
| { status: "success"; data: string }
| { status: "error"; message: string };
// const bad: State = { status: "success", data: "x", message: "y" };
// Allowed extra props would be flagged in strict object checks.
console.log("no contradictory states");حماية الانتقالات غير الصالحة
يمكنك تجاهل الأحداث التي لا تنطبق على الحالة الحالية، والحفاظ على الآلة في حالة متسقة بدلًا من تعطلها.
type State = { status: "idle" } | { status: "loading" };
type Event = { type: "FETCH" } | { type: "CANCEL" };
function reduce(s: State, e: Event): State {
if (s.status === "loading" && e.type === "CANCEL") return { status: "idle" };
if (s.status === "idle" && e.type === "FETCH") return { status: "loading" };
return s; // ignore invalid combos
}
console.log(reduce({ status: "loading" }, { type: "CANCEL" }).status);إضافة اكتمال الحالات
اربط المخفّض بالدالة assertNever، حتى تؤدي إضافة حالة أو حدث جديد إلى إظهار كل موضع يجب تحديثه.
function assertNever(x: never): never { throw new Error("unhandled"); }
type State = { status: "idle" } | { status: "loading" } | { status: "done"; data: string };
function view(s: State): string {
switch (s.status) {
case "idle": return "idle";
case "loading": return "loading";
case "done": return s.data;
default: return assertNever(s);
}
}
console.log(view({ status: "done", data: "ok" }));الحالات الأولية والنهائية
حدّد حالة بداية واضحة، غالبًا idle، وحالات نهائية، مثل success أو error. وبذلك توثّق دورة حياة الآلة.
type State =
| { status: "idle" }
| { status: "loading" }
| { status: "success"; data: string }
| { status: "error"; message: string };
const initial: State = { status: "idle" };
console.log("Start:", initial.status);آلة حالات مصغّرة مكتملة
إليك الدورة كاملة: تبدأ الآلة في حالة الخمول، ثم تنتقل عبر fetch إلى التحميل، ثم تنتقل بعد اكتمال العملية إلى النجاح. وتحافظ الأنواع على صحة كل خطوة.
type State = { status: "idle" } | { status: "loading" } | { status: "success"; data: string };
type Event = { type: "FETCH" } | { type: "RESOLVE"; data: string };
function reduce(s: State, e: Event): State {
if (e.type === "FETCH") return { status: "loading" };
return { status: "success", data: e.data };
}
let st: State = { status: "idle" };
st = reduce(st, { type: "FETCH" });
st = reduce(st, { type: "RESOLVE", data: "hi" });
console.log(st.status, st.status === "success" ? st.data : "");تحقق سريع: آلات الحالات
اختبر فهمك لنمذجة آلات الحالات.
مراجعة: نمذجة آلات الحالات
نمذجت حالات الخمول والتحميل والنجاح والخطأ كاتحاد مميّز، وكتبت انتقالات آمنة من ناحية الأنواع اعتمادًا على اتحادي الحالة والحدث، واستخدمت اكتمال الحالات للحفاظ على صحة الآلة أثناء توسعها.
type State = { status: "idle" } | { status: "loading" } | { status: "success"; data: string };
const s: State = { status: "success", data: "done" };
console.log(s.status === "success" ? s.data : "");الأسئلة الشائعة
هل درس «نمذجة آلات الحالات» مجاني؟
نعم — نص درس «نمذجة آلات الحالات» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة TypeScript Academy، انتقل إلى CoddyKit PRO. تتضمن دورة TypeScript Academy 4 دروس في المجموع.
ماذا ستتعلم في «نمذجة آلات الحالات»؟
مثّلوا الحالات المحدودة باستخدام الاتحادات المميّزة تتمرن على TypeScript Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ TypeScript Academy؟
لا تُشترط خبرة سابقة. TypeScript Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «نمذجة آلات الحالات»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس TypeScript Academy هذا؟
نعم. كل درس في TypeScript Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- بناء الاتحادات المميّزة
- تضييق النوع اعتمادًا على المميّز
- التحقق من اكتمال الحالات باستخدام never
- نمذجة آلات الحالات