الاتحادات المميّزة لأشكال المكوّنات
صمّم خصائص الأشكال باستخدام اتحادات مميّزة حتى يفرض TypeScript مجموعات الخصائص الصحيحة.
الاتحادات المميّزة لأشكال المكوّنات درس مجاني في React Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في React Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة React Academy 4 دروس في المجموع.
مشكلة خصائص الأنماط المتنوعة
قد يحتوي المكوّن الذي لديه خصائص اختيارية لأوضاع مختلفة (مثل زر يمكن أن يكون رابطًا أو زرًا) على مجموعات غير صالحة من الخصائص. ولا يستطيع TypeScript اكتشاف ذلك من دون الاتحادات المميّزة.
ما الاتحاد المميّز؟
الاتحاد المميّز هو اتحاد من الأنواع تشترك في حقل نوع حرفي مشترك (حقل التمييز). ويضيّق TypeScript نوع القيمة بناءً على قيمة ذلك الحقل.
type Shape =
| { kind: 'circle'; radius: number }
| { kind: 'rectangle'; width: number; height: number };
function area(shape: Shape): number {
if (shape.kind === 'circle') return Math.PI * shape.radius ** 2;
return shape.width * shape.height; // TS knows width/height exist here
}نمط الزر مقابل الرابط
مثّل مكوّنًا متعدد الأشكال باستخدام اتحاد مميّز في حقل as أو variant لفرض الخصائص الصحيحة لكل حالة.
type ButtonProps =
| { as: 'button'; onClick: () => void; disabled?: boolean; children: React.ReactNode }
| { as: 'a'; href: string; target?: string; children: React.ReactNode };
function ActionButton(props: ButtonProps) {
if (props.as === 'button') {
return <button onClick={props.onClick} disabled={props.disabled}>{props.children}</button>;
}
return <a href={props.href} target={props.target}>{props.children}</a>;
}أنماط مكوّن التنبيه
مثّل مكوّن Alert ببيانات مختلفة مطلوبة لكل نوع من أنواع مستوى الخطورة.
type AlertProps =
| { type: 'success'; message: string }
| { type: 'error'; message: string; onRetry: () => void }
| { type: 'warning'; message: string; details?: string };
function Alert(props: AlertProps) {
if (props.type === 'error') {
return (
<div className="alert error">
<p>{props.message}</p>
<button onClick={props.onRetry}>Retry</button>
</div>
);
}
return <div className={`alert ${props.type}`}>{props.message}</div>;
}تضييق النوع في معالجات الأحداث
تعمل الاتحادات المميّزة مع البيانات المعتمدة على الأحداث أيضًا — وهي مناسبة جدًا لآلات الحالة أو للحالة المعتمدة على الإجراءات.
type LoadingState<T> =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: T }
| { status: 'error'; error: Error };
function DataView<T>({ state }: { state: LoadingState<T> }) {
if (state.status === 'loading') return <Spinner />;
if (state.status === 'error') return <p>{state.error.message}</p>;
if (state.status === 'success') return <pre>{JSON.stringify(state.data)}</pre>;
return null;
}التحقق الشامل باستخدام never
أضف فحصًا باستخدام never في الفرع الافتراضي لتحصل على خطأ من TypeScript إذا أُضيف عضو جديد إلى الاتحاد ولم تتم معالجته.
function assertNever(x: never): never {
throw new Error('Unhandled case: ' + x);
}
function renderIcon(type: AlertProps['type']) {
switch (type) {
case 'success': return <CheckIcon />;
case 'error': return <XIcon />;
case 'warning': return <WarnIcon />;
default: return assertNever(type); // TS error if a case is missing
}
}الاتحادات المميّزة لاستجابات API
مثّل أشكال استجابات API باستخدام اتحادات مميّزة، حتى يعالج المستدعون مساري النجاح والخطأ من دون تحويل النوع.
type ApiResult<T> =
| { ok: true; data: T }
| { ok: false; error: string; code: number };
async function fetchUser(id: string): Promise<ApiResult<User>> {
const res = await fetch(`/api/users/${id}`);
if (!res.ok) return { ok: false, error: 'Not found', code: res.status };
return { ok: true, data: await res.json() };
}حواجز النوع للتضييق
استخدم حواجز نوع مخصصة لتضييق الاتحادات في السيناريوهات الأكثر تعقيدًا، حيث لا يكون التمييز مجرد فحص للمساواة.
function isSuccess<T>(result: ApiResult<T>): result is { ok: true; data: T } {
return result.ok === true;
}
const result = await fetchUser('1');
if (isSuccess(result)) {
console.log(result.data.name); // TS knows data exists
}تجنب فوضى الخصائص الاختيارية
من دون الاتحادات المميّزة، تتراكم في المكونات خصائص اختيارية لا تكون صالحة إلا في مجموعات معينة، مما يجعلها مربكة وغير مقيّدة بالأنواع. وتزيل الاتحادات المميّزة الحالات المستحيلة.
// Bad: optional prop soup — invalid combos allowed:
interface BadProps {
href?: string;
onClick?: () => void;
disabled?: boolean;
}
// Good: only valid combos via discriminated union:
type GoodProps =
| { as: 'a'; href: string }
| { as: 'button'; onClick: () => void; disabled?: boolean };تركيب الاتحادات
استخدم & (التقاطع) لإضافة الخصائص المشتركة إلى جميع أعضاء الاتحاد.
type BaseProps = { className?: string; children: React.ReactNode };
type ButtonVariant =
| (BaseProps & { variant: 'primary'; onClick: () => void })
| (BaseProps & { variant: 'link'; href: string });التمييز وقت التشغيل
يستخدم React حقل التمييز وقت التشغيل لعرض واجهة المستخدم الصحيحة. ويستخدمه TypeScript وقت الترجمة لفرض الاستخدام الصحيح للخصائص. وبذلك تكون كلتا الطبقتين محميتين.
تحقق سريع
ما حقل التمييز في الاتحاد المميّز؟
مراجعة
تمثّل الاتحادات المميّزة المكونات ذات مجموعات الخصائص المتنافية من خلال مشاركة حقل تمييز ذي نوع حرفي. استخدم never في الفرع الافتراضي لإجراء فحوص شاملة. فهي تزيل مجموعات الخصائص غير الصالحة التي تسمح بها الخصائص الاختيارية، مما يجعل المكونات موضّحة ذاتيًا وآمنة من ناحية الأنواع.
الأسئلة الشائعة
هل درس «الاتحادات المميّزة لأشكال المكوّنات» مجاني؟
نعم — نص درس «الاتحادات المميّزة لأشكال المكوّنات» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة React Academy، انتقل إلى CoddyKit PRO. تتضمن دورة React Academy 4 دروس في المجموع.
ماذا ستتعلم في «الاتحادات المميّزة لأشكال المكوّنات»؟
صمّم خصائص الأشكال باستخدام اتحادات مميّزة حتى يفرض TypeScript مجموعات الخصائص الصحيحة. تتمرن على React Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ React Academy؟
لا تُشترط خبرة سابقة. React Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.
كم من الوقت يستغرق درس «الاتحادات المميّزة لأشكال المكوّنات»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس React Academy هذا؟
نعم. كل درس في React Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- الاتحادات المميّزة لأشكال المكوّنات
- الأنواع الشرطية والمُعيّنة في React
- المكوّنات متعددة الأشكال باستخدام خاصية 'as'
- النماذج الآمنة نوعيًا وعقود استجابات API