JSON في TypeScript: 5 أخطاء قاتلة عند التحويل وكيفية إصلاحها

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: أسطورة التحويل "السحري" للأنواع

\n\n

كل مطور TypeScript يواجه عاجلاً أم آجلاً هذا الموقف: تحصل على JSON من الخادم، وتكون متأكداً من هيكله، وتقوم بتحويل بسيط باستخدام as. ثم... لا يعمل شيء. دوال الكلاس مفقودة، الحقول undefined، ويصبح التصحيح مهمة شاقة.

\n\n

سؤال "How do I cast a JSON object to a TypeScript class?" هو من أكثر الأسئلة شيوعاً على Stack Overflow (عشرات الآلاف من المشاهدات). وهذا ليس مفاجئاً. TypeScript هي إضافة موجودة فقط أثناء التجميع. في وقت التشغيل، "الكلاس" الخاص بك هو مجرد كائن JavaScript عادي.

\n\n

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

\n\n

الخطأ رقم 1: استخدام as للتحويل "الحقيقي"

\n\n

أكثر فخ شائع هو الاعتقاد أن التركيب jsonData as MyClass ينشئ مثيلاً من الكلاس.

\n\n

ماذا يحدث في الواقع؟

\n

عامل as (أو صيغة الأقواس الزاوية) هو تأكيد نوع. يخبر المترجم: "ثق بي، أنا أعرف النوع". لكنه لا يقوم بأي سحر في JavaScript.

\n\n
class User {\n    name: string = '';\n    greet(): string {\n        return `مرحباً، ${this.name}!`;\n    }\n}\n\nconst rawData = JSON.parse('{"name": "آنا"}');\nconst user = rawData as User;\n\nconsole.log(user.name); // "آنا" — يعمل\nconsole.log(user.greet()); // TypeError: user.greet is not a function\n
\n\n

لماذا؟ لأن rawData هو كائن عادي { name: 'آنا' }. ليس لديه النموذج الأولي User.prototype، وبالتالي لا يملك الدالة greet.

\n\n

كيفية الإصلاح؟

\n

قم دائماً بإنشاء مثيل حقيقي من الكلاس. الطريقة الأساسية هي Object.assign:

\n\n
const user = Object.assign(new User(), rawData);\nconsole.log(user.greet()); // "مرحباً، آنا!"\n
\n\n

لكن لهذه الطريقة تفاصيل دقيقة سنناقشها لاحقاً.

\n\n

الخطأ رقم 2: تجاهل الكائنات والمصفوفات المتداخلة

\n\n

تستخدم Object.assign بسعادة، لكن بياناتك تحتوي على هياكل متداخلة. وهنا تبدأ المشكلة.

\n\n
class Address {\n    city: string = '';\n    zip: string = '';\n}\n\nclass Company {\n    name: string = '';\n    address: Address = new Address();\n}\n\nconst data = JSON.parse('{"name": "TechCorp", "address": {"city": "موسكو", "zip": "101000"}}');\nconst company = Object.assign(new Company(), data);\n\nconsole.log(company.address.city); // "موسكو" — حظ موفق؟\nconsole.log(company.address instanceof Address); // false!\n
\n\n

المشكلة: address بقي كائنًا بسيطًا، وليس مثيلاً من Address. إذا كان لدى Address دوال أو خصائص محسوبة، فستفقد.

\n\n

الحل: التحويل التكراري

\n

اكتب دالة مصنع أو استخدم مكتبة class-transformer:

\n\n
import { plainToClass } from 'class-transformer';\n\nconst company = plainToClass(Company, data);\nconsole.log(company.address instanceof Address); // true\n
\n\n

class-transformer يتجاوز جميع الحقول بشكل تكراري وينشئ مثيلات صحيحة من الكلاسات بناءً على الديكورات @Type.

\n\n

الخطأ رقم 3: فقدان القيم الافتراضية

\n\n

TypeScript يسمح بتعيين قيم افتراضية للحقول مباشرة في الكلاس. لكن عند "تحويل" JSON، قد يتم استبدال هذه القيم بـ undefined.

\n\n
class Config {\n    theme: string = 'light';\n    fontSize: number = 14;\n    language: string = 'ru';\n}\n\nconst partialData = JSON.parse('{"theme": "dark"}');\nconst config = Object.assign(new Config(), partialData);\n\nconsole.l                

المدونات

توصيات الكتب