عند استقبال بيانات من واجهة برمجية، أول ما يخطر ببال المطور هو كيف أحوّلها إلى أنواع. الأداة في هذا الموقع تفعل ذلك في ثوانٍ، لكن النتيجة ليست نهاية القصة. الفهم الصحيح للفرق بين الشكل المتوقع والسلوك الفعلي هو ما يفصل بين كود آمن وكود ينهار في الإنتاج.
ما الذي تلتقطه الأداة فعلاً
أداة التحويل تمر على ملف JSON حقيقي، لذا ترى القيم الموجودة فيه فقط. هذا يعني:
- إذا ظهر حقل في مثال واحد فقط، قد يُولَّد كنص بينما هو رقم في بقية الحالات.
- إذا ظهر الحقل بقيمة فارغة في موضع ما، ستظهر خاصية تقبل القيمة الفارغة.
- إذا رأيت نوعين مختلفين في الحقل نفسه، ستحصل على نوع بديل وهذا صحيح.
الفرق بين الحقل الغائب والقيمة الفارغة
أكثر مصادر أخطاء TypeScript هو الخلط بين مفتاح غير موجود ومفتاح موجود قيمته فارغة. الحالة الثالثة هي مفتاح قد لا يوجد أصلاً، وهي أصعب الحالات:
| الحالة في البيانات | الشكل الصحيح | الشرح |
|---|---|---|
| المفتاح غائب تماماً | field?: string | قد لا يوجد المفتاح أصلاً |
| المفتاح موجود وقيمته null | field: string | null | المفتاح موجود لكن القيمة فارغة |
| المفتاح قد يكون أياً منهما | field: string | null | undefined | الأكثر أماناً مع بيانات خارجية |
type User = {
id: number;
name: string;
nickname: string | null; // موجود دائماً لكن قد تكون القيمة فارغة
avatar?: string; // قد لا يوجد المفتاح أصلاً
role: "admin" | "editor" | "viewer" | null;
};استخدم نوعاً بديلاً محدداً بدل أي نص
إن كان حقل مقيّداً بقائمة قيم، فاجعله نوعاً بديلاً من قيم محددة. هذا ينقل الخطأ من وقت التشغيل إلى وقت الترجمة، وهو أنجح بكثير:
// قبل: أي نص مقبول
type Order = { status: string };
// بعد: القيم المسموحة محددة
type OrderStatus = "pending" | "paid" | "shipped" | "cancelled";
type Order = { status: OrderStatus };
// الآن هذا خطأ ترجمة، قبل أن يصل إلى الإنتاج
const bad: Order = { status: "deliverd" };تجنب any والتأكيدات العشوائية
إن استخدمت any فأنت تطفئ فحص الأنواع. الأفضل استخدام unknown الذي يفرض عليك التحقق قبل الاستخدام:
function render(data: unknown) {
// TypeScript يفرض عليك التحقق قبل الاستخدام
if (typeof data === "object" && data !== null && "name" in data) {
const name = (data as { name: string }).name;
console.log(name);
}
}الأنواع لا تحميك عند التشغيل
النوع في TypeScript يُمسح عند الترجمة، فلا يوجد تحقق فعلي من أن الخادم يُرجع ما أعلنه. لذلك فإن التحقق وقت التشغيل ضروري مع البيانات القادمة من الخارج:
type User = { id: number; name: string };
function isUser(value: unknown): value is User {
return (
typeof value === "object" &&
value !== null &&
typeof (value as User).id === "number" &&
typeof (value as User).name === "string"
);
}
const data: unknown = await fetch("/api/user").then(res => res.json());
if (isUser(data)) {
console.log(data.name); // أصبح آمناً هنا
}سير عمل مقترح
- خزّن الاستجابة الحقيقية من الواجهة البرمجية في ملف JSON.
- ولّد الأنواع تلقائياً من هذا الملف.
- راجع الأنواع يدوياً: عدّل الخصائص الاختيارية والقيم الفارغة وتعدد الأنواع.
- أضف التحقق وقت التشغيل عند الحد الذي تدخل فيه البيانات غير الموثوقة.
- اكتب اختبارات للحالات الحدّية: مفتاح غائب، قيمة فارغة، ونوع خاطئ.
هذا السير يحوّل النسخ واللصق إلى عملية قابلة للمراجعة، وهذا بالضبط ما تحتاجه في مشروع حقيقي.