TypeScript: شرح مفصل لملف tsconfig.json في TypeScript

آخر تحديث: 2026-08-26

يُعد ملف tsconfig.json مركز التكوين لمشاريع TypeScript — فهو يحدد للمترجم كيفية ترجمة الكود، والتحقق من الأنواع، وإخراج النتائج. ويُعد فهم خيارات التكوين هذه أمرًا ضروريًا لضمان سير مشروع TypeScript الخاص بك بسلاسة.

1. أساسيات ملف tsconfig.json

(1) إنشاء ملف تكوين

BASH
# Automatically Generate Default Configuration
tsc --init

# Generate a detailed configuration with comments
tsc --init --typescript

(2) الهيكل الأساسي

JSON
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "strict": true,
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

(3) الحقول ذات المستوى الأعلى

الحقل الوصف
compilerOptions خيارات المُترجم
include الملفات المضمنة (وضع glob)
exclude الملفات المستبعدة
files قائمة الملفات المحددة صراحةً
references مراجع المشروع (مستودع واحد)
extends التوريث من ملف تكوين آخر


2. خيارات التجميع الأساسية

(1) الهدف — هدف التجميع

حدد إصدار جافا سكريبت المُجمَّع:

JSON
{
  "compilerOptions": {
    "target": "ES2020"
  }
}
القيمة الوصف السيناريوهات الموصى بها
"ES5" متوافق مع المتصفحات القديمة يدعم IE11
"ES2018" المتصفحات الحديثة مشاريع الويب العامة
"ES2020" أحدث الميزات في الإصدار المستقر موصى به
"ESNext" أحدث ميزات المقترحات مشاريع رائدة
💡 نصيحة: لا يؤثر الخيار target إلا على تحويل الصيغة (مثل: الدوال السهمية → الدوال العادية)؛ ولا يؤثر على فحص الأنواع. يتم التحكم في فحص الأنواع بواسطة الخيار lib.

(2) الوحدة — نظام الوحدات

JSON
{
  "compilerOptions": {
    "module": "ESNext"
  }
}
القيمة الوصف السيناريوهات الموصى بها
"CommonJS" الإعدادات الافتراضية لـ Node.js مشروع Node
"ESNext" / "ES2015" وحدات ES متصفح/Deno/Vite
"UMD" الوحدات النمطية متعددة الأغراض إصدارات المكتبة
"System" SystemJS مُحمِّل الوحدات النمطية القديم

(3) moduleResolution — استراتيجية تحديد دقة الوحدة النمطية

JSON
{
  "compilerOptions": {
    "moduleResolution": "node"
  }
}
القيمة الوصف
"node" نمط Node.js (موصى به)
"classic" النمط القديم لـ TS (غير موصى به)
"bundler" Vite/esbuild وأدوات البناء الأخرى (TS 5.0+)

(4) lib — مكتبة الأنواع

حدد إعلانات الأنواع المدمجة المتاحة:

JSON
{
  "compilerOptions": {
    "lib": ["ES2020", "DOM", "DOM.Iterable"]
  }
}
القيمة النوع المُقدَّم
"ES2020" Promise، Array.flat، BigInt، إلخ.
"DOM" المستند، النافذة، HTMLElement، إلخ.
"DOM.Iterable" NodeList 's for...of
"ES2020.String" ES2020: طرق معالجة السلاسل
"ES2020.Promise" Promise.allSettled، وما إلى ذلك
💡 نصيحة: يتم تضمين target تلقائيًا مع lib المقابل. إذا قمت بتحديد lib صراحةً، فلن يتم تضمينه تلقائيًا بعد ذلك — وستحتاج إلى إدراج جميع المكتبات المطلوبة يدويًّا. عادةً ما تتطلب مشاريع الويب ["ES2020", "DOM"].

(5) outDir و rootDir

JSON
{
  "compilerOptions": {
    "outDir": "./dist",      // Compilation Output Directory
    "rootDir": "./src",      // Source Code Root Directory(Preserve the directory structure)
    "declaration": true,     // Generate .d.ts Statement
    "sourceMap": true        // Generate .js.map Source Code Mapping
  }
}


3. خيار «الوضع الصارم»

(1) تم تمكين الوضع الصارم بالكامل

JSON
{
  "compilerOptions": {
    "strict": true
  }
}

strict: true يعادل تفعيل جميع الخيارات التالية في آن واحد:

الخيار الوصف
strictNullChecks لا يمكن تعيين القيمة «فارغ/غير معرّف» إلى أنواع أخرى
strictFunctionTypes الفحص العكسي لمعلمات الدالة
strictBindCallApply الفحص الدقيق لـ bind/call/apply
strictPropertyInitialization يجب تهيئة خصائص الفئة
noImplicitAny غير صريح any محظور
noImplicitThis عدم السماح باستخدام «this» الضمني كـ «any»
alwaysStrict إصدار "use strict"

(2) فهم كل نقطة

TYPESCRIPT
// strictNullChecks: true
let name: string = null;    // ❌ null Cannot be assigned string
let name2: string | null = null;  // ✅ Explicit Declaration

// noImplicitAny: true
function greet(name) {      // ❌ The parameter is implicitly set to any
  return name;
}
function greet2(name: string) {  // ✅ Explicit Annotation
  return name;
}

// strictPropertyInitialization: true
class User {
  name: string;    // ❌ Property not initialized
  age: number = 0; // ✅ Has an initial value
}
📌 توصية: قم بتمكين strict لجميع المشاريع الجديدة. فهو حجر الزاوية في أمان الأنواع في TypeScript — ورغم أن إضافة تعليقات الأنواع قد تتطلب مجهودًا إضافيًا في البداية، إلا أنها تساعد في منع عدد كبير من أخطاء وقت التشغيل.

▶ مثال: مقارنة بين الوضع الصارم وما قبله وما بعده

TYPESCRIPT
// strict: false — the following code does not generate any errors, but it may crash during execution.
let name: string = null as any;    // Runtime name.toUpperCase() Breakdown
function greet(user) {             // user Implicit any
  return user.name;                // No type checking
}

// strict: true — captured at compile time
let name2: string | null = null;   // ✅ Must be explicitly declared null
function greet2(user: { name: string }) {  // ✅ Parameters must be labeled
  return user.name;
}
▶ جرّب الكود

الناتج:

TEXT 📖 للعرض فقط
// Executed successfully


4. تكوين الوحدات والمسارات

(1) تعيين المسار

JSON
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "@utils/*": ["src/utils/*"],
      "@components/*": ["src/components/*"]
    }
  }
}

(2) resolveJsonModule

JSON
{
  "compilerOptions": {
    "resolveJsonModule": true,
    "esModuleInterop": true
  }
}
TYPESCRIPT
// Import Allowed JSON Documents
import config from "./config.json";
console.log(config.port);  // ✅

(3) allowJs مع checkJs

JSON
{
  "compilerOptions": {
    "allowJs": true,    // Allow compilation JS Documents
    "checkJs": false    // Do not check JS File Type(Compile Only)
  }
}
💡 الغرض: عند ترحيل مشروع JS إلى TS تدريجيًّا، ابدأ بتمكين allowJs للسماح بتعايش TS وJS، ثم أضف الأنواع تدريجيًّا.



5. خيارات جودة الكود

JSON
{
  "compilerOptions": {
    "noUnusedLocals": true,       // Error: Unused local variables
    "noUnusedParameters": true,   // Error: Unused function parameters
    "noImplicitReturns": true,    // Error: Function branch does not return a value
    "noFallthroughCasesInSwitch": true,  // Error: switch fallthrough
    "forceConsistentCasingInFileNames": true  // File names must be case-sensitive
  }
}

(1) عرض توضيحي

TYPESCRIPT
// noUnusedLocals: true
let unused = 42;    // ❌ Unused variables

// noUnusedParameters: true
function handler(event: Event) {  // ❌ event Unused
  console.log("Trigger");
}
// Fix: Use _ prefix tag
function handler2(_event: Event) {  // ✅ _ The prefix does not cause an error
  console.log("Trigger");
}

// noImplicitReturns: true
function getGrade(score: number): string {
  if (score >= 90) return "A";
  if (score >= 80) return "B";
  // ❌ Missing else Branched return
}

// noFallthroughCasesInSwitch: true
switch (action) {
  case "create":
    createItem();
    // ❌ Missing break——case Penetration
  case "update":
    updateItem();
    break;
}


6. قوالب التكوين الشائعة

(1) مشروع الخلفية باستخدام Node.js

JSON
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "CommonJS",
    "moduleResolution": "node",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "declaration": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist", "**/*.test.ts"]
}

(2) مشروع واجهة مستخدم باستخدام React (Vite)

JSON
{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "baseUrl": ".",
    "paths": { "@/*": ["src/*"] }
  },
  "include": ["src"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

(3) مشاريع المكتبات (نشر حزم npm)

JSON
{
  "compilerOptions": {
    "target": "ES2018",
    "module": "ESNext",
    "moduleResolution": "node",
    "declaration": true,
    "declarationDir": "./dist/types",
    "outDir": "./dist/esm",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist", "**/*.test.ts"]
}

▶ مثال: تأثيرات تكوين target وmodule

TYPESCRIPT
// The same source code compiles differently based on target/module settings
async function fetchData(): Promise<string> {
  let response = await Promise.resolve("hello");
  return response.toUpperCase();
}

export function greet(name: string): string {
  return `Hello, ${name}!`;
}
▶ جرّب الكود

الناتج:

TEXT 📖 للعرض فقط
Compilation output varies by target/module — see explanations below

With "target": "ES5", async/await compiles to a verbose state machine; with "target": "ES2020", it stays as native async/await. With "module": "CommonJS", exports become exports.greet = greet; with "module": "ESNext", they remain as export function greet.


▶ مثال: التحقق الصارم من القيم الخالية في الممارسة العملية

TYPESCRIPT
// strictNullChecks: true prevents common null bugs
interface User { name: string; email: string | null; }

function getDisplayName(user: User): string {
  // return user.email.toLowerCase(); // ❌ Object is possibly null
  return user.email ? user.email.toLowerCase() : user.name; // ✅
}

function findUser(id: number): User | null {
  return id > 0 ? { name: "Alice", email: "a@b.com" } : null;
}

let user = findUser(1);
// console.log(user.name); // ❌ user is possibly null
if (user) {
  console.log(user.name); // ✅ narrowed to User
}
▶ جرّب الكود

الناتج:

TEXT 📖 للعرض فقط
Alice

❓ أسئلة شائعة

س هل تجعل strict كتابة الكود أكثر صعوبة؟
ج قد تتطلب في البداية المزيد من تعليقات الأنواع (خاصةً لفحوصات القيمة الفارغة)، ولكن على المدى الطويل، فإنها تقلل بشكل كبير من الأخطاء التي تحدث أثناء التشغيل. نوصي بتمكين strict منذ البداية — فبمجرد أن تعتاد عليها، ستجد في الواقع أنه من غير المريح عدم استخدامها. إذا كان مشروعك كبيرًا بالفعل، فيمكنك تمكينه تدريجيًا: قم أولًا بتمكين noImplicitAny، ثم strictNullChecks، وأخيرًا قم بتمكين strict بالكامل.
س ما هو noEmit؟ ولماذا تم إنشاء مشروع Vite؟
ج noEmit: true يسمح لـ TypeScript بإجراء فحص الأنواع فقط دون إنتاج ملفات JS. يستخدم مشروع Vite أداة Vite (esbuild) للتحويل البرمجي والتجميع، بينما يقتصر دور tsc على فحص الأنواع فقط — لذا لا داعي لأن يقوم tsc بإنتاج ملفات. استخدم tsc --noEmit للتحقق من الأنواع في CI، ودع Vite يتولى التجميع في الوقت الفعلي أثناء التطوير.
س هل ينبغي تمكين skipLibCheck؟
ج نوصي بتمكينه. تعمل ميزة skipLibCheck على تخطي فحص الأنواع لملفات .d.ts، مما قد يؤدي إلى تسريع عملية الترجمة بشكل ملحوظ. الجانب السلبي هو أنه قد يتجاهل أخطاء في إعلانات الأنواع الخاصة بأطراف ثالثة — لكن المخاطرة منخفضة للغاية (حزمة @types تخضع لمراجعة المجتمع). يمكن أن يؤدي تمكين skipLibCheck في المشاريع الكبيرة إلى توفير 30% أو أكثر من وقت الترجمة.
س ما الغرض من استخدام extends لتوريث التكوين؟
ج عندما يحتوي المشروع على عدة ملفات tsconfig (مثل الواجهة الأمامية، ونصوص Node، والاختبارات)، استخدم extends لمشاركة التكوين الأساسي وتجاوز الاختلافات فقط. يمكن لـ tsconfig.node.json أن extends tsconfig.json، مع تعديل الخيارات مثل target وmodule فقط. وهذا يتجنب تكرار التكوين.

📖 ملخص

📝 تمارين

  1. تمرين أساسي (مستوى الصعوبة ⭐): استخدم tsc --init لإنشاء ملف tsconfig.json الافتراضي، وقم بتغيير target إلى ES2020، وقم بتمكين strict، واضبط outDir على dist. أنشئ ملف TypeScript بسيطًا، وقم بتجميعه، وتأكد من أنه يعمل.
  2. تمرين متقدم (مستوى الصعوبة ⭐⭐): قم بتكوين ملف tsconfig.json يدعم الاسم المستعار للمسار @/*src/*. أنشئ src/utils/math.ts وsrc/main.ts، واستخدم الاسم المستعار لاستيراد الدوال من math.ts إلى main.ts.
  3. التحدي (مستوى الصعوبة: ⭐⭐⭐): صمم تسلسلاً هرميًا للتكوين لمشروع أحادي المستودع — الأساسي tsconfig.base.json (خيارات مشتركة)، وpackages/app/tsconfig.json (يمتد من الأساسي، واجهة مستخدم React)، وpackages/server/tsconfig.json (يمتد من الأساسي، الخلفية Node) — واستخدم references لربط المشروعين الفرعيين.
Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%