Skip to content
العودة إلى المدوّنة
دروس تعليمية

تحويل JSON إلى TypeScript: توليد الواجهات والأنواع (دليل 2026)

حوّل JSON إلى واجهات TypeScript بالطريقة الصحيحة: قواعد استنتاج الأنواع، interface مقابل type، الحقول الاختيارية والاتحادية، والأخطاء الشائعة. جرّبه مجانًا.

11 دقيقة قراءة

تحويل JSON إلى TypeScript: توليد الواجهات والأنواع (دليل 2026)

أسرع طريقة للانتقال من JSON إلى TypeScript هي لصق الحمولة (payload) في محوّل JSON إلى TypeScript ونسخ الواجهة (interface) التي يولّدها: بلا تثبيت، بلا رفع، ينتهي الأمر داخل متصفحك. هذا يغطي حالة «أحتاج الأنواع الآن».

لكن توليد الأنواع وتوليد أنواع جيدة أمران مختلفان. على المحوّل أن يخمّن: هل هذا الحقل اختياري أم أنه غائب فقط من عيّنة واحدة؟ هل تلك المصفوفة دائمًا نصوص، أم أحيانًا أرقام أيضًا؟ هل ينبغي أن يصبح نص التاريخ من النوع Date؟ يشرح هذا الدليل كيف يعمل الاستنتاج فعليًا، ومتى تلجأ إلى interface مقابل type، والأخطاء الحقيقية في تحويل استجابات الـ API الحيّة إلى أنواع يمكنك الوثوق بها.

كيفية تحويل JSON إلى TypeScript

يستغرق تحويل JSON إلى TypeScript ثلاث خطوات:

  1. الصق الـ JSON. أسقِط كائنًا أو مصفوفة أو استجابة API خامًا في صندوق الإدخال. يجري التحويل فورًا، بالكامل من جانب العميل (client-side).
  2. اضبط المخرجات. اختر interface أو type، وعيّن اسمًا للجذر مثل User أو ApiResponse، وبدّل الكلمة المفتاحية export، واختر ?: أو | null للحقول الاختيارية.
  3. انسخ أو نزّل. احصل على الـ TypeScript المولّد بنقرة واحدة والصقه مباشرة في قاعدة شفرتك.

هذا كل شيء بالنسبة للمسار العملي. يقرأ محوّل JSON إلى TypeScript المدخلات، ويستنتج شجرة أنواع، ويطبع التعريفات على اليمين، ولا شيء يغادر الصفحة. بقية هذا الدليل تدور حول فهم ما أنتجه حتى تتمكن من إصلاح الحالات التي لا يستطيع تخمينها.

كيف تُطابِق أنواع JSON أنواع TypeScript

لكل قيمة JSON نظير في TypeScript. المطابقة في معظمها واحد لواحد:

قيمة JSONنوع TypeScript
"text"string
42, 3.14number
true / falseboolean
nullnull
[1, 2, 3]number[]
{ ... }interface أو type

الكائنات هي حيث يجري العمل الفعلي. خذ حمولة مستخدم REST نموذجية:

{
  "id": 101,
  "name": "Ada Lovelace",
  "email": "ada@example.com",
  "active": true,
  "roles": ["admin", "user"]
}

يُنتج المحوّل واجهة TypeScript هذه من الـ JSON:

export interface User {
  id: number;
  name: string;
  email: string;
  active: boolean;
  roles: string[];
}

تُطابَق كل قيمة قياسية (scalar) نوعها الأولي، وتصبح مصفوفة roles من النوع string[]. أسقِط ذلك في عميل الـ API فتحصل على الإكمال التلقائي والفحوص وقت الترجمة مجانًا.

كيف يستنتج المحوّل الأنواع

يقوم العمل كله على خوارزمية الاستنتاج، وأربع قواعد تغطي تقريبًا كل ما ستلقيه عليها.

الاستنتاج البنيوي: واجهة واحدة مسمّاة لكل كائن

يصبح كل شكل كائن متمايز واجهةً مسمّاة خاصة به. الكائنات المتداخلة لا تنطوي في أنواع مضمّنة (inline)، بل تُرفع إلى تعريفات منفصلة ومُشار إليها:

{
  "order": {
    "id": "A-1",
    "total": 42.5,
    "customer": { "name": "Sam", "vip": false }
  }
}
export interface Root {
  order: Order;
}

export interface Order {
  id: string;
  total: number;
  customer: Customer;
}

export interface Customer {
  name: string;
  vip: boolean;
}

تُزال تكرارات الأشكال المتطابقة، بحيث يتشارك حقلان لهما البنية نفسها واجهةً واحدة بدلًا من إنتاج نسخ.

دمج المصفوفات: استنتاج الحقول الاختيارية

عندما تمرّر مصفوفة من الكائنات، يدمجها المحوّل مفتاحًا بمفتاح. إذا ظهر مفتاح في بعض العناصر دون غيرها، فإنه يُعلَّم اختياريًا:

{
  "users": [
    { "id": 1, "nick": "x" },
    { "id": 2 }
  ]
}
export interface Root {
  users: User[];
}

export interface User {
  id: number;
  nick?: string;
}

id موجود في كل عنصر، لذا يبقى مطلوبًا. nick غائب من المستخدم الثاني، لذا يصبح nick?: string. لهذا السبب نادرًا ما تكفي عيّنة واحدة؛ راجع قسم الأخطاء أدناه.

الأنواع الاتحادية للمصفوفات المختلطة

لا يلزم أن تكون المصفوفات متجانسة. عندما تختلف أنواع العناصر، يجمعها المحوّل في اتحاد (union):

{
  "tags": ["a", "b"],
  "meta": [1, "two"]
}
export interface Root {
  tags: string[];
  meta: (string | number)[];
}

tags نصوص بشكل موحّد، لذا string[]. meta يخلط رقمًا ونصًا، فيُنتج (string | number)[]. مصفوفة فارغة لا يمكن استنتاجها على الإطلاق وتتراجع إلى unknown[]، وهذا صادق، إذ لا شيء يُتعلَّم من صفر عناصر.

الاختياري مقابل null: ?: مقابل | null

يبدوان متشابهين لكنهما يعنيان أمرين مختلفين. حقل مُعلَّم بـ ?: قد يكون غائبًا عن الكائن كليًا. حقل مُحدَّد نوعه بـ | null يكون حاضرًا دائمًا لكنه قد يحمل القيمة null:

{ "score": null }
export interface Root {
  score: number | null;
}

هنا score حاضر بقيمة null صريحة، لذا يُحدَّد نوعه number | null؛ القيمة موجودة، لكنها فقط null. قارن ذلك بـ nick?: string من مثال المصفوفة، حيث يمكن أن يكون المفتاح غائبًا تمامًا. الجأ إلى ?: حين قد يحذف الـ API المفتاح، وإلى | null حين يرسل المفتاح بقيمة null. معظم المحوّلات تتيح لك التحكم في كيفية عرض ذلك عبر مبدّل.

interface مقابل type: أيهما تستخدم؟

كلاهما يستطيع وصف شكل كائن. إليك كيف تقرر:

الحاجةاستخدم
شكل كائن بسيط من JSONinterface
اتحاد (A | B) أو تقاطع (A & C)type
دمج التصريحات (declaration merging) / التوسعة عبر الملفاتinterface
الأنواع المُطابَقة (mapped) أو الشرطية (conditional)type
رسائل أخطاء أنظف قليلًا في المحررinterface

بالنسبة للبيانات الناتجة عن كائن JSON، يُعدّ interface الخيار المتعارف عليه وينتج أخطاء مُترجِم أنظف بقليل. في اللحظة التي تحتاج فيها إلى اتحاد، مثل Result يكون إما نجاحًا أو خطأ، عليك التحوّل إلى type، لأن الواجهات لا تستطيع التعبير عن الاتحادات:

type ApiResult =
  | { status: "ok"; data: User }
  | { status: "error"; message: string };

خيار افتراضي جيد: ولّد interface لكائنات JSON البسيطة، وحوّل إلى type حين يحتاج الشكل إلى اتحاد أو تقاطع. يغطي دليل TypeScript (TypeScript Handbook) الحالات الحدّية إذا أردت المقارنة الكاملة. حين تحتاج إلى اسم نوع (json to typescript type) بدلًا من واجهة، تكشف معظم المحوّلات مبدّلًا واحدًا لقلب المخرجات بأكملها.

quicktype مقابل json-to-ts مقابل الأدوات عبر الإنترنت مقابل اليدوي

لا توجد طريقة واحدة أفضل لتوليد أنواع TypeScript؛ يعتمد الأمر على مكان وجود الـ JSON ومدى تكرار تغيّره.

النهجالأنسب لـالمقايضة
quicktypeالمخرجات متعددة اللغات، توليد شفرة تحقق وقت التشغيلأثقل؛ مخرجات أكثر مما تحتاج غالبًا
json-to-ts (مكتبة)توليد الشفرة وقت البناء مدمجًا في سكربت أو خط أنابيبيتطلب إعدادًا وأدوات Node
أداة عبر الإنترنت تعمل في المتصفحالتحويلات لمرة واحدة، الحمولات الحساسة، صفر تثبيتلصق يدوي في كل مرة
كتابة الأنواع يدويًاالكائنات الصغيرة جدًا، تعلّم نظام الأنواعممل وعرضة للخطأ على نطاق واسع

اختر quicktype حين تحتاج أنواعًا بعدة لغات أو تريده أن يصدر مُتحقِّقات (validators) إلى جانب الأنواع. اختر مكتبة json-to-ts حين ينتمي التحويل إلى خطوة بناء. للتحويل السريع، خاصةً لحمولة تحتوي على رموز (tokens) أو معرّفات عملاء أو أي شيء تفضّل عدم لصقه في خدمة بعيدة، تفوز أداة المتصفح في الخصوصية والسرعة. يعمل محوّل JSON إلى TypeScript لدينا بالكامل من جانب العميل: الـ JSON لا يغادر الصفحة أبدًا، ولا شيء لتثبيته أو تحديثه.

الأنواع ليست تحققًا: الجسر إلى فحوص وقت التشغيل

هذا يربك فرقًا كثيرة، لذا يستحق القول بوضوح: أنواع TypeScript تُمحى وقت الترجمة ولا تفعل شيئًا وقت التشغيل. واجهة مولّدة interface User لن تتحقق من أن استجابة API فعلية تطابقها. إذا أرسل الخادم id كنص بدلًا من رقم، يصدّق TypeScript بسعادة تعليقك التوضيحي للنوع بينما البيانات الحقيقية تكذب.

لكي تولّد أنواع TypeScript (generate typescript types) و تفرضها على بيانات حيّة، اقرن الأنواع بمُتحقِّق وقت تشغيل:

  • zod — عرّف مخططًا مرة واحدة، واستنتج النوع الساكن منه، وحلّل الاستجابات وقت التشغيل.
  • io-ts — تحقق قائم على المرمّزات (codec)، شائع في قواعد الشفرة الوظيفية.
  • JSON Schema + Ajv — مخططات محايدة اللغة يتم التحقق منها وقت التشغيل، مفيدة حين يكون العقد مشتركًا عبر الخدمات.

نمط شائع هو توليد الواجهة لدعم المحرر، ثم كتابة مخطط zod مطابق بوصفه فحص الحدود الفعلي:

import { z } from "zod";

const UserSchema = z.object({
  id: z.number(),
  name: z.string(),
  email: z.string().email(),
  active: z.boolean(),
  roles: z.array(z.string()),
});

type User = z.infer<typeof UserSchema>;

// يطرح خطأً إذا لم تطابق الاستجابة الحقيقية المخطط.
const user = UserSchema.parse(await res.json());

إذا كنت تسلك مسار المخطط، فإن دليل التحقق من JSON بـ JSON Schema لدينا يشرح كتابة المخططات وفرضها من البداية إلى النهاية.

أخطاء شائعة عند تحديد أنواع JSON

الأنواع المولّدة نقطة بداية، لا منتج نهائي. انتبه لهذه.

snake_case مقابل camelCase. يحتفظ المحوّل بالمفاتيح حرفيًا. حمولة بأسلوب GitHub تحتوي على public_repos تُنتج public_repos: number، لا publicRepos. إذا كانت قاعدة شفرتك تفضّل camelCase، فستتعايش إما مع أنواع snake_case أو تضيف طبقة مطابقة تعيد تسمية الحقول عند الدخول.

نصوص التواريخ تبقى string. حقل مثل “2026-06-01T00:00:00Z” يُحدَّد نوعه string، لا Date. هذا متعمّد، فلا يملك JSON نوع تاريخ، والتخمين الخاطئ أسوأ من الصدق. تحويل النص إلى Date ينتمي إلى طبقة التحليل (parsing) لديك، حيث تتحكم به.

تسرّب any وunknown. تصبح المصفوفات الفارغة unknown[]، والبنى المختلطة عميقًا قد تتدهور إلى أنواع فضفاضة. هذه ليست أخطاء؛ إنها اعتراف المحوّل بأنه لا يستطيع الاستنتاج من بيانات غير كافية. أحكِمها يدويًا حالما تعرف الشكل الحقيقي.

انفجار التداخل العميق. حمولة متداخلة بكثافة تولّد سلسلة طويلة من الواجهات الصغيرة. هذا عادةً لا بأس به وأكثر قابلية للقراءة من نوع مضمّن عملاق واحد، لكن يستحق تسطيح الأشكال التي لا تستحق اسمًا خاصًا بها.

فخ العيّنة الواحدة. هذا هو الأهم. لا يمكن استنتاج الحقول الاختيارية إلا من عناصر مصفوفة متعددة، فكائن واحد لا يستطيع إخبار المحوّل بأي المفاتيح غائبة أحيانًا. اجمع مصفوفة تمثيلية من الاستجابات أولًا. منسق JSON مفيد للصق وفحص عدة عيّنات جنبًا إلى جنب قبل التحويل، وإذا كنت تُغذّي مدخلات غير قياسية مثل JSONC، فاقرأ دليل JSON5 / JSONC، فالمحوّل يحتاج إلى JSON صالح تمامًا.

أسئلة شائعة

كيف أحوّل JSON إلى واجهة TypeScript؟

الصق الـ JSON في محوّل JSON إلى TypeScript. يقرأ المدخلات في متصفحك ويولّد واجهة TypeScript فورًا. انقر «نسخ» للحصول على النتيجة: بلا رفع، بلا حساب، بلا مكوّن إضافي لتثبيته.

هل أستخدم interface أم type لبيانات JSON؟

استخدم interface لأشكال الكائنات البسيطة من JSON، فهو المتعارف عليه ويعطي أخطاء محرر أوضح قليلًا. تحوّل إلى type حين تحتاج إلى اتحاد أو تقاطع، إذ لا تستطيع الواجهات التعبير عن ذلك.

كيف تُعالَج الكائنات والمصفوفات المتداخلة؟

تصبح الكائنات المتداخلة واجهات منفصلة مسمّاة (حقل address يُنتج واجهة Address). تُدمج مصفوفات الكائنات مفتاحًا بمفتاح في واجهة عنصر واحدة؛ وتصبح المصفوفات الأولية مصفوفات محدَّدة النوع مثل string[].

كيف تُحدَّد أنواع الحقول الاختيارية والـ null؟

مفتاح غائب من بعض عناصر المصفوفة يُعلَّم اختياريًا (nick?: string). مفتاح حاضر دائمًا لكنه يحمل null يُحدَّد نوعه بـ | null (score: number | null). الاثنان يصفان وضعين مختلفين: غائب مقابل حاضر-لكن-null.

هل تتحقق أنواع TypeScript من JSON وقت التشغيل؟

لا. أنواع TypeScript تُمحى وقت الترجمة ولا تفحص البيانات وقت التشغيل. للتحقق من استجابة API فعلية، اقرن الأنواع المولّدة بمُتحقِّق وقت تشغيل مثل zod أو io-ts أو JSON Schema مع Ajv.

quicktype مقابل json-to-ts مقابل محوّل عبر الإنترنت — أيها أفضل؟

يناسب quicktype المخرجات متعددة اللغات ومُتحقِّقات وقت التشغيل؛ وتناسب مكتبة json-to-ts توليد الشفرة وقت البناء؛ ويناسب المحوّل عبر الإنترنت التحويلات السريعة الخاصة لمرة واحدة بصفر تثبيت. للحمولات الحساسة، تُبقي أداة المتصفح من جانب العميل البيانات بعيدًا عن أي خادم.

لماذا تُحدَّد أنواع نصوص التواريخ بـ string بدلًا من Date؟

لا يملك JSON نوع تاريخ، فالتاريخ مجرد نص على الشبكة. تحديد نوعه بـ string صادق ومستقر؛ والتحويل إلى Date قرار يخص طبقة التحليل لديك، حيث تتحكم بالتنسيق ومعالجة الأخطاء.

هل بيانات JSON الخاصة بي خاصة عند استخدام محوّل عبر الإنترنت؟

مع أداة من جانب العميل، نعم. يجري التحويل بالكامل في متصفحك باستخدام JavaScript، لذا فإن الـ JSON، بما في ذلك الرموز والمعرّفات وبيانات العملاء، لا يغادر الصفحة أبدًا ولا يُرسل إلى خادم.

مقالات ذات صلة

عرض جميع المقالات