deepkit/type TypeScript: دليل شامل مع أمثلة

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

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

ابدأ الدورة

deepkit/type لـ TypeScript: دليل شامل مع أمثلة

في عالم TypeScript، هناك مشكلة أساسية: الأنواع (Types) موجودة فقط في مرحلة الترجمة. بعد التحويل إلى JavaScript، تختفي كل المعلومات عن الأنواع. هذا يجعل من المستحيل التحقق من صحة البيانات في وقت التشغيل (runtime validation)، أو التسلسل الديناميكي (dynamic serialization)، أو بناء أنظمة معقدة تعتمد على بيانات وصفية للأنواع. مكتبة deepkit/type تحل هذه المشكلة بشكل جذري — فهي تنقل نظام أنواع TypeScript إلى وقت التشغيل، مما يسمح بالتعامل مع الأنواع كبيانات.

القيمة الأساسية لـ deepkit/type تكمن في أنها لا تتطلب كتابة مخططات مكررة (كما في Zod أو Yup). أنت تصف الأنواع مرة واحدة — بلغة TypeScript الخالصة — والمكتبة تستخرجها تلقائيًا في وقت التشغيل. هذا يتيح لك إمكانية التحقق من صحة البيانات، التسلسل/إلغاء التسلسل، الانعكاس (الحصول على معلومات حول الخصائص، الأنواع العامة، الزخارف)، وحتى إنشاء كود بناءً على الأنواع. deepkit/type ليست مجداة أداة تحقق، بل هي إطار عمل متكامل للبرمجة الوصفية (metaprogramming).

المكتبة مثالية للمشاريع التي تتطلب كتابة أنواع صارمة على جميع المستويات: خوادم API (التحقق من صحة الطلبات الواردة)، قواعد البيانات (ربط الأنواع بـ SQL)، ملفات الإعدادات، أنظمة RPC، وأدوات إنشاء الكود. بفضل التكامل مع deepkit/framework، تُستخدم أيضًا لبناء تطبيقات خادم عالية الأداء مع تحقق وتسلسل تلقائي.

التثبيت

deepkit/type هي حزمة npm لـ TypeScript. يتم التثبيت باستخدام الأمر القياسي:

npm install @deepkit/type reflect-metadata

ستحتاج أيضًا إلى إعداد ملف tsconfig.json لدعم الزخارف (decorators) وإصدار البيانات الوصفية:

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "strict": true,
    "target": "ES2020",
    "module": "commonjs",
    "outDir": "./dist"
  }
}

إذا كنت تستخدم ts-node للتشغيل، تأكد من تحميل reflect-metadata أولاً. أضف السطر التالي في بداية ملف الدخول (entry file):

import 'reflect-metadata';

بداية سريعة

مثال بسيط يوضح كيفية تعريف نوع والحصول على تمثيله في وقت التشغيل:

import 'reflect-metadata';
import { typeOf, ReflectionClass } from '@deepkit/type';

// تعريف واجهة
interface User {
  id: number;
  name: string;
  email?: string;
}

// الحصول على النوع في وقت التشغيل
const userType = typeOf();
console.log(userType); // ReflectionClass

// التحقق من الخصائص
const reflection = ReflectionClass.from(userType);
console.log(reflection.getProperty('name').type); // ReflectionProperty
console.log(reflection.getProperty('id').type.kind); // 'number'

هذا الكود سيعرض معلومات عن نوع User في وحدة التحكم. لاحظ: لم نكتب أي مخططات — فقط واجهة TypeScript خالصة.

الدوال والوظائف الرئيسية

فيما يلي الإمكانيات الرئيسية لـ deepkit/type. لكل دالة، نقدم التوقيع (signature)، وصفًا مختصرًا، ومثالًا عمليًا.

1. typeOf

التوقيع: typeOf<T>(): ReflectionClass

الوظيفة: تستخرج تمثيل النوع T في وقت التشغيل. تُرجع كائن ReflectionClass يحتوي على معلومات كاملة عن بنية النوع: الخصائص، أنواعها، المعدّلات (اختياري، للقراءة فقط)، الأنواع العامة، والزخارف.

import { typeOf } from '@deepkit/type';

interface Product {
  id: number;
  title: string;
  price: number;
}

const productType = typeOf();
console.log(productType.getProperty('title').type.kind); // 'string'
console.log(productType.getProperty('price').type.kind); // 'number'

2. is

التوقيع: is<T>(value: unknown): value is T

الوظيفة: تتحقق مما إذا كانت القيمة المعطاة تطابق النوع T في وقت التشغيل. تعمل كحارس نوع (type guard) في TypeScript.

import { is } from '@deepkit/type';

interface User {
  id: number;
  name: string;
}

const data: unknown = { id: 1, name: 'أحمد' };

if (is(data)) {
  console.log(data.name); // TypeScript يعرف أن data من نوع User
}

3. cast

التوقيع: cast<T>(value: unknown): T

الوظيفة: تحوّل القيمة المعطاة إلى النوع T، مع تطبيق التحويلات الافتراضية (مثل تحويل السلاسل النصية إلى أرقام). ترمي خطأ إذا كان التحويل غير ممكن.

import { cast } from '@deepkit/type';

interface Config {
  port: number;
  host: string;
}

const raw = { port: '3000', host: 'localhost' };
const config = cast(raw);
console.log(config.port); // 3000 (رقم)

4. serialize

التوقيع: serialize<T>(value: T): any

الوظيفة: تحوّل قيمة من النوع T إلى كائن JSON عادي، مع تطبيق قواعد التسلسل المخصصة (مثل تجاهل الخصائص أو تحويل التواريخ).

import { serialize } from '@deepkit/type';

interface User {
  id: number;
  name: string;
  password: string;
}

const user: User = { id: 1, name: 'سارة', password: 'secret' };
const serialized = serialize(user);
console.log(serialized); // { id: 1, name: 'سارة', password: 'secret' }

5. deserialize

التوقيع: deserialize<T>(value: any): T

الوظيفة: تحوّل كائن JSON عادي إلى قيمة من النوع T، مع تطبيق قواعد إلغاء التسلسل (مثل تحويل التواريخ من سلسلة نصية).

import { deserialize } from '@deepkit/type';

interface User {
  id: number;
  name: string;
  createdAt: Date;
}

const json = { id: 1, name: 'خالد', createdAt: '2024-01-15T10:00:00Z' };
const user = deserialize(json);
console.log(user.createdAt instanceof Date); // true

6. ReflectionClass

التوقيع: ReflectionClass.from(type: ReflectionClass): ReflectionClass

الوظيفة: توفّر واجهة للاستعلام عن بنية النوع: الحصول على الخصائص، أنواعها، الزخارف، والأنواع العامة. يمكن استخدامها لبناء أدوات ديناميكية.

import { typeOf, ReflectionClass } from '@deepkit/type';

interface User {
  id: number;
  name: string;
  email?: string;
}

const userType = typeOf();
const reflection = ReflectionClass.from(userType);

// الحصول على جميع الخصائص
const properties = reflection.getProperties();
properties.forEach(prop => {
  console.log(`${prop.name}: ${prop.type.kind} (اختياري: ${prop.optional})`);
});
// id: number (اختياري: false)
// name: string (اختياري: false)
// email: string (اختياري: true)

الخلاصة

deepkit/type هي أداة قوية تنقل نظام أنواع TypeScript إلى وقت التشغيل، مما يفتح آفاقًا جديدة للتحقق من البيانات، التسلسل، والبرمجة الوصفية. باستخدام هذه المكتبة، يمكنك كتابة كود TypeScript آمن وخالٍ من التكرار، مع الحفاظ على الأداء العالي. جربها في مشروعك القادم!

توصيات