إتقان JavaScript و TypeScript
أنماط TypeScript في المقابلات
أصبح TypeScript الآن متطلبًا أساسيًا لمعظم أدوار الواجهات الأمامية. تختبر المقابلات قدرتك على استخدام نظام الأنواع لكتابة كود أكثر أمانًا وقابلية للصيانة — وليس مجرد إضافة تعليقات : string.
أنواع المساعدة (Utility Types)
هذه الأنواع المدمجة تظهر باستمرار في المقابلات. احفظها عن ظهر قلب:
interface User {
id: number;
name: string;
email: string;
role: 'admin' | 'user' | 'guest';
createdAt: Date;
}
// Pick: اختيار خصائص محددة
type UserPreview = Pick<User, 'id' | 'name'>;
// { id: number; name: string }
// Omit: استبعاد خصائص محددة
type UserWithoutDates = Omit<User, 'createdAt'>;
// { id: number; name: string; email: string; role: ... }
// Partial: جعل جميع الخصائص اختيارية
type UpdateUser = Partial<User>;
// { id?: number; name?: string; email?: string; ... }
// Required: جعل جميع الخصائص مطلوبة
type CompleteUser = Required<Partial<User>>;
// العودة لكل الخصائص مطلوبة
// Record: إنشاء نوع كائن بأنواع مفتاح-قيمة محددة
type RolePermissions = Record<User['role'], string[]>;
// { admin: string[]; user: string[]; guest: string[] }
// Readonly: جعل جميع الخصائص للقراءة فقط
type FrozenUser = Readonly<User>;
// لا يمكن إعادة تعيين أي خصائص
الأنواع العامة (Generics)
الأنواع العامة تتيح لك كتابة كود قابل لإعادة الاستخدام وآمن الأنواع:
// دالة عامة أساسية
function getFirst<T>(arr: T[]): T | undefined {
return arr[0];
}
getFirst([1, 2, 3]); // number
getFirst(['a', 'b']); // string
// عام مع قيود
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const user: User = { id: 1, name: 'Alice', email: 'a@b.com', role: 'admin', createdAt: new Date() };
getProperty(user, 'name'); // string
getProperty(user, 'role'); // 'admin' | 'user' | 'guest'
// getProperty(user, 'age'); // خطأ: 'age' ليس في keyof User
الأنواع الشرطية (Conditional Types)
هذه قوية لبناء أدوات أنواع مرنة:
// نوع شرطي أساسي
type IsString<T> = T extends string ? true : false;
type A = IsString<string>; // true
type B = IsString<number>; // false
// استخراج الأنواع غير القابلة للإلغاء
type NonNullable<T> = T extends null | undefined ? never : T;
type C = NonNullable<string | null | undefined>; // string
// كلمة infer: استخراج الأنواع من أنواع أخرى
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
type D = ReturnType<() => string>; // string
type E = ReturnType<(x: number) => boolean>; // boolean
// مثال عملي: استخراج النوع الداخلي لـ Promise
type Awaited<T> = T extends Promise<infer U> ? Awaited<U> : T;
type F = Awaited<Promise<string>>; // string
type G = Awaited<Promise<Promise<number>>>; // number
الاتحادات المميزة (Discriminated Unions)
نمط يظهر بشكل متكرر في خصائص مكونات React:
// بدلاً من خصائص اختيارية مع شروط معقدة،
// استخدم الاتحادات المميزة
type ButtonProps =
| { variant: 'link'; href: string; onClick?: never }
| { variant: 'button'; onClick: () => void; href?: never }
| { variant: 'submit'; form: string; href?: never; onClick?: never };
function Button(props: ButtonProps) {
switch (props.variant) {
case 'link':
return <a href={props.href}>Link</a>;
case 'button':
return <button onClick={props.onClick}>Click</button>;
case 'submit':
return <button type="submit" form={props.form}>Submit</button>;
}
}
// TypeScript يضيّق النوع في كل فرع حالة
// props.href يمكن الوصول إليه فقط عندما يكون variant هو 'link'
حراس الأنواع (Type Guards)
حراس الأنواع المخصصة تنقّح الأنواع في وقت التشغيل:
// دالة توقع النوع مع `is`
function isString(value: unknown): value is string {
return typeof value === 'string';
}
// استخدام عامل `in`
interface Dog { bark(): void; }
interface Cat { meow(): void; }
function isDog(pet: Dog | Cat): pet is Dog {
return 'bark' in pet;
}
// التحقق الشامل مع `never`
type Shape = { kind: 'circle'; radius: number }
| { kind: 'square'; side: number }
| { kind: 'triangle'; base: number; height: number };
function area(shape: Shape): number {
switch (shape.kind) {
case 'circle':
return Math.PI * shape.radius ** 2;
case 'square':
return shape.side ** 2;
case 'triangle':
return 0.5 * shape.base * shape.height;
default:
// إذا تمت إضافة شكل جديد ولم يُعالج،
// سيعطي TypeScript خطأ هنا في وقت الترجمة
const _exhaustive: never = shape;
return _exhaustive;
}
}
أنواع القوالب الحرفية (Template Literal Types)
مفيدة لإنشاء أنواع سلاسل نصية دقيقة:
type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
type APIPath = '/users' | '/posts' | '/comments';
// الجمع في سلاسل مسارات
type APIRoute = `${HTTPMethod} ${APIPath}`;
// 'GET /users' | 'GET /posts' | ... (12 تركيبة)
// عملي: أنواع خصائص CSS
type CSSUnit = 'px' | 'rem' | 'em' | '%' | 'vh' | 'vw';
type CSSValue = `${number}${CSSUnit}`;
const width: CSSValue = '100px'; // صالح
const height: CSSValue = '50rem'; // صالح
// const bad: CSSValue = 'auto'; // خطأ
نصيحة للمقابلات: عندما يُطلب منك "تحسين أمان الأنواع" لجزء من الكود، ابحث عن فرص لاستخدام الاتحادات المميزة والأنواع العامة مع القيود وأنواع القوالب الحرفية. هذه تُظهر فهمًا عميقًا لـ TypeScript يتجاوز التعليقات التوضيحية الأساسية.
التالي: سنغطي الأنماط غير المتزامنة ومعالجة الأخطاء — الموضوع الرئيسي الآخر في JavaScript الذي يُعثّر المرشحين. :::