لماذا لا يعيش TypeScript في فراغ؟
\nعندما نكتب بلغة TypeScript، نعتاد على صرامتها، والإكمال التلقائي، والأصناف العامة (Generics). لكن عاجلاً أم آجلاً، يواجه كل مطور سؤالاً: "ماذا لو احتجت إلى استدعاء كود بلغة Python أو C++ أو Go؟". هل سأعيد كتابة المشروع بأكمله؟
\nالخبر السار: TypeScript ليس جزيرة معزولة. إنه قادر على التعاون مع اللغات الأخرى عبر الوحدات الأصلية، و WebAssembly، و gRPC، وحتى الجسور العادية عبر HTTP. في هذه المقالة، سنستعرض ثلاثة سيناريوهات حقيقية لتكامل TypeScript مع لغات أخرى. ستتعلم كيفية ربط الواجهة الأمامية، والخلفية، والحوسبة عالية الأداء في حزمة واحدة.
\n\nالسيناريو 1: TypeScript + Python — علم البيانات معززاً
\nPython هو ملك التعلم الآلي وتحليل البيانات. لكن نقطة ضعفه هي واجهات الويب. على العكس، يعمل TypeScript بشكل رائع في المتصفح وعلى الخادم. من المنطقي الجمع بين قواهما.
\n\nالطريقة أ: خدمة مصغرة عبر HTTP (الأسهل)
\nالطريقة الأكثر وضوحاً هي تشغيل خادم Python (مثل FastAPI) واستدعائه من TypeScript باستخدام fetch.
\nPython (backend.py):
\nfrom fastapi import FastAPI\nfrom pydantic import BaseModel\nimport joblib\n\napp = FastAPI()\nmodel = joblib.load('model.pkl')\n\nclass InputData(BaseModel):\n features: list[float]\n\n@app.post("/predict")\ndef predict(data: InputData):\n result = model.predict([data.features])\n return {"prediction": result.tolist()}\n\nTypeScript (frontend.ts):
\ninterface PredictionResponse {\n prediction: number[];\n}\n\nasync function getPrediction(features: number[]): Promise<number[]> {\n const response = await fetch('http://localhost:8000/predict', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ features })\n });\n \n if (!response.ok) throw new Error('خطأ في التوقع');\n \n const data: PredictionResponse = await response.json();\n return data.prediction;\n}\n\n// الاستخدام\ngetPrediction([1.2, 3.4, 5.6])\n .then(pred => console.log('النتيجة:', pred))\n .catch(err => console.error(err));\n\n\nالطريقة ب: نصوص Python عبر child_process (للخلفية)
\nإذا كنت لا تحتاج إلى خادم منفصل، يمكنك تشغيل Python مباشرة من Node.js. هذا مناسب للمهام الفردية مثل معالجة الصور أو إنشاء التقارير.
\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\n\nconst execPromise = promisify(exec);\n\nasync function runPythonScript(scriptPath: string, args: string[]): Promise<string> {\n const command = `python3 ${scriptPath} ${args.join(' ')}`;\n const { stdout, stderr } = await execPromise(command);\n \n if (stderr) throw new Error(`خطأ في Python: ${stderr}`);\n return stdout.trim();\n}\n\n// مثال: تمرير JSON إلى Python\nconst result = await runPythonScript('./analyze.py', ['--data', '{"value": 42}']);\nconsole.log('Python أجاب:', result);\n\nهام: هذا الأسلوب أبطأ من الخدمة المصغرة، لكنه لا يتطلب إعداد خادم منفصل. مناسب للنماذج الأولية و CI/CD.
\n\nالسيناريو 2: TypeScript + C++ — سرعة خيالية
\nعندما تحتاج إلى معالجة الفيديو أو الصوت أو التشفير، قد لا يكون Python كافياً. هنا يأتي دور C++ وحليفه القوي WebAssembly (WASM).
\n\nترجمة C++ إلى WASM واستدعاؤه من TypeScript
\nلنفترض أن لدينا دالة بسيطة بلغة C++ لتسريع ضرب المصفوفات:
\n// matrix.cpp\nextern "C" {\n void multiply_matrices(float* a, float* b, float* result, int size) {\n for (int i = 0; i < size; i++) {\n for (int j = 0; j < size; j++) {\n float sum = 0.0f;\n for (int k = 0; k < size; k++) {\n sum += a[i * size + k] * b[k * size + j];\n