Menu
flag Ar iconالعربيةdown icon

شرح tsconfig.json: الخيارات والقيم الافتراضية مع أمثلة

ملف tsconfig.json يجعل المجلد مشروع TypeScript ويضبط خيارات المترجم. الخيارات المهمة (target وmodule وmoduleResolution وstrict وrootDir وoutDir وinclude وlib وtypes وnoEmit وskipLibCheck)، وإعداد مقترح للبداية، وextends، وما غيّرته TypeScript 7.

تحتوي هذه الصفحة على محررات قابلة للتشغيل - حرّر، شغّل، وشاهد النتيجة فوراً.

tsconfig.json هو ملف إعدادات مشروع TypeScript. عندما تشغّل tsc دون وسائط، يبحث المترجم عنه في المجلد الحالي (ثم في المجلدات الأعلى)، ويقرأ الخيارات في compilerOptions، ويفحص الملفات التي يحددها include. إليك ملفًا صغيرًا لكنه كامل:

{
    "compilerOptions": {
        "target": "es2022",
        "module": "nodenext",
        "strict": true,
        "rootDir": "./src",
        "outDir": "./dist"
    },
    "include": ["src"]
}

يترجم هذا كل ملف TypeScript في src إلى JavaScript في dist، ككود ES2022، باستخدام قواعد الوحدات في Node.js، مع تفعيل كل الفحوص الصارمة. ويولّد npx tsc --init ملف بداية أطول مع تعليق على كل خيار.

الملف JSON مع تعليقات: تُقبل تعليقات // وتعليقات /* */ والفواصل الزائدة في النهاية.

إعداد مقترح للبداية

لتطبيق أو سكربت Node.js:

{
    "compilerOptions": {
        "rootDir": "./src",
        "outDir": "./dist",

        "target": "es2024",
        "lib": ["es2024"],
        "module": "nodenext",
        "types": ["node"],

        "strict": true,
        "noUncheckedIndexedAccess": true,
        "verbatimModuleSyntax": true,
        "skipLibCheck": true,
        "sourceMap": true
    },
    "include": ["src"]
}

يحتاج إلى npm install --save-dev @types/node للحصول على أنواع Node.js. مع module: "nodenext" يقرر الحقل "type" في package.json ما إذا كان ملف .ts وحدة ES ("type": "module") أو CommonJS ("type": "commonjs"، وهي القيمة التي يكتبها npm init -y). استخدم "type": "module" في المشاريع الجديدة التي تستخدم import وexport.

وللكود الذي تبنيه أداة تجميع مثل Vite أو esbuild أو webpack، تكتب الأداة كود JavaScript ويكتفي tsc بالفحص:

{
    "compilerOptions": {
        "target": "es2022",
        "lib": ["es2022", "dom"],
        "module": "preserve",
        "noEmit": true,

        "strict": true,
        "noUncheckedIndexedAccess": true,
        "verbatimModuleSyntax": true,
        "isolatedModules": true,
        "skipLibCheck": true,
        "jsx": "react-jsx"
    },
    "include": ["src"]
}

قوالب البدء في أطر العمل (Vite وNext.js وAngular) تولّد ملف tsconfig.json الخاص بها. ابدأ من ملفها بدل استبداله.

الخيارات المهمة

الخياروظيفتهالقيمة الافتراضية في TypeScript 7
targetإصدار JavaScript للناتج؛ الصياغة الأحدث يُعاد كتابتها للأهداف الأقدمes2025
libأنواع الواجهات البرمجية المدمجة التي يعرفها الفاحص (Array.prototype.at وMap وdocument)تطابق target، إضافة إلى DOM
moduleنوع كود الوحدات الناتج وقواعد الوحدات المطبقةesnext
moduleResolutionكيف يُعثر على مسارات الاستيراد على القرصnodenext أو node16 مع module المطابق، وإلا bundler
strictيفعّل عائلة الفحوص الصارمة كلهاtrue
rootDirالمجلد الذي تُنسخ بنيته إلى outDirالمجلد الذي يحتوي على tsconfig.json
outDirمكان ملفات .js (و.d.ts)بجانب كل ملف مصدري
include / exclude / filesالملفات التي تنتمي إلى المشروعكل ملف .ts تحت المجلد
typesحزم @types التي تُحمَّل دون استيراد[]، لا شيء
noEmitفحص فقط، دون كتابة أي شيءfalse
declarationكتابة ملفات تعريف الأنواع .d.ts أيضًاfalse
sourceMapكتابة ملفات .js.map لأدوات التصحيحfalse
esModuleInteropيجعل import x from "cjs-package" يعمل مع حزم CommonJStrue (لا يمكن تعطيله)
skipLibCheckتخطي فحص أنواع ملفات .d.ts، ومنها ما في node_modulesfalse

target و lib

يحدد target إصدار JavaScript الذي يجب أن يعمل عليه الناتج. الصياغة الأحدث من الهدف يُعاد كتابتها: مع "target": "es2017" يتحول حقل الصنف أو ??= إلى كود أقدم. أدنى هدف تقبله TypeScript 7 هو es2015 (es6)؛ وقد أُزيل es5.

لا يضيف target الواجهات البرمجية الناقصة وقت التشغيل. وصفها مهمة lib، وتوفيرها مهمة polyfill. يخبر lib الفاحص بالكائنات والدوال المدمجة الموجودة. قيمته الافتراضية تتبع target وتتضمن أيضًا أنواع DOM الخاصة بالمتصفح، لذلك يجتاز document فحص الأنواع حتى في مشروع Node.js ما لم تضبط lib بنفسك. استخدام دالة من معيار أحدث من lib يسبب خطأ ترجمة:

src/b.ts(1,24): error TS2550: Property 'toSorted' does not exist on type 'number[]'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2023' or later.

تستخدم الأمثلة القابلة للتشغيل في هذا التوثيق lib بقيمة es2022، لذلك لا تتوفر فيها toSorted وObject.groupBy ودوال Set الجديدة.

module و moduleResolution

لـ module ثلاث قيم معقولة في الكود الجديد:

  • nodenext: للكود الذي يشغّله Node.js. كل ملف يكون ESM أو CommonJS بحسب امتداده (.mts و.cts) أو الحقل "type" في أقرب package.json، تمامًا كما يقرر Node. الاستيرادات النسبية في وحدات ES تحتاج إلى امتداد ملف، يُكتب .js رغم أن المصدر .ts: import { add } from "./math.js". ويتبعه moduleResolution تلقائيًا.
  • preserve: للكود الذي تعالجه أداة تجميع. تُترك الاستيرادات كما كُتبت، ويستخدم التحليل قواعد bundler التي تسمح بالاستيراد دون امتداد.
  • esnext: ناتج وحدات ES عادي، مع تحليل bundler. وهي القيمة الافتراضية عندما لا يُضبط module.

خطأ أول شائع مع إعداد tsc --init سببه أن npm init -y يكتب "type": "commonjs":

src/main.ts(1,10): error TS1295: ECMAScript imports and exports cannot be written in a CommonJS file under 'verbatimModuleSyntax'.

يستخدم الملف import، لكن package.json يقول إن المشروع CommonJS. غيّر "type" إلى "module". تغطي صفحة الوحدات الاستيراد والتصدير بالتفصيل.

strict وخيارات الفحص

يفعّل "strict": true مجموعة من الفحوص دفعة واحدة: noImplicitAny وstrictNullChecks وstrictFunctionTypes وstrictBindCallApply وstrictPropertyInitialization وstrictBuiltinIteratorReturn وnoImplicitThis وuseUnknownInCatchVariables. وهو الافتراضي في TypeScript 7 ومفعّل في كل مثال قابل للتشغيل هنا. الكود المكتوب للوضع الصارم يضيّق النوع قبل استخدام قيمة قد تكون غائبة:

دون تعليق نوع، لا يمكن استنتاج نوع المعامل، فيبلّغ noImplicitAny عن ذلك:

index.ts(2,17): error TS7006: Parameter 'n' implicitly has an 'any' type.

لا يتضمن strict كل فحص مفيد. اثنان يستحقان الإضافة هما noUncheckedIndexedAccess (عنصر المصفوفة أو القراءة عبر index signature يكون نوعه T | undefined) وexactOptionalPropertyTypes (لا يمكن ضبط خاصية اختيارية صراحة على undefined)؛ ويفعّلهما tsc --init كليهما. أما فحوص الأسلوب مثل noUnusedLocals وnoImplicitReturns وnoFallthroughCasesInSwitch فمعطلة افتراضيًا.

أي الملفات: include وexclude وrootDir وoutDir

دون include أو files يحتوي المشروع على كل ملف .ts و.tsx و.d.ts في المجلد ومجلداته الفرعية. يُستبعد node_modules دائمًا. ويُستبعد outDir أيضًا، لكن فقط ما دمت لم تضبط exclude: قائمة exclude مخصصة تحل محل هذا الافتراض، فأضف مجلد الناتج إليها. تقبل include وexclude أنماط glob:

{
    "include": ["src", "scripts/**/*.ts"],
    "exclude": ["src/**/*.test.ts"]
}

لا يفعل exclude سوى تصفية ما وجده include. الملف الذي يستورده ملف آخر مُضمَّن يُترجم رغم ذلك.

outDir هو مكان الناتج، وrootDir هو الجزء من شجرة المصدر الذي تُنسخ بنيته إليه: مع "rootDir": "./src" يصبح src/api/users.ts هو dist/api/users.js. اضبط الاثنين. القيمة الافتراضية لـ rootDir هي المجلد الذي يحتوي على tsconfig.json، لذلك إذا ضبطت outDir فقط والمصادر في src، تتوقف TypeScript 7 بهذا الخطأ:

error TS5011: The common source directory of 'tsconfig.json' is './src'. The 'rootDir' setting must be explicitly set to this or another path to adjust your output's file layout.

خيارات الناتج: noEmit وdeclaration وsourceMap

  • "noEmit": true يجعل tsc فاحص أنواع فقط. استخدمه عندما تنتج أداة أخرى كود JavaScript (أداة تجميع أو tsx أو حذف الأنواع في Node.js).
  • "declaration": true يكتب ملف .d.ts لكل وحدة، أي الأنواع دون الكود. تحتاج إليه المكتبات حتى يحصل مستخدموها على الأنواع. ويضيف declarationMap خرائط تجعل «الانتقال إلى التعريف» يصل إلى مصدر .ts.
  • "sourceMap": true يكتب ملفات .js.map حتى تشير أدوات التصحيح وتتبع الأخطاء إلى أسطر .ts.
  • "noEmitOnError": true لا يكتب شيئًا ما دامت هناك أخطاء أنواع. دونه يبلّغ tsc عن الأخطاء ويكتب JavaScript مع ذلك.

types وesModuleInterop وskipLibCheck

يسرد types حزم @types التي تُحمَّل عالميًا دون استيراد. القيمة الافتراضية في TypeScript 7 قائمة فارغة، لذلك بعد npm install --save-dev @types/node تضيف أيضًا "types": ["node"]؛ وإلا يبقى process وrequire مجهولين (error TS2591: Cannot find name 'process'). مشغلات الاختبار ذات الدوال العامة، مثل describe في Jest، توضع في القائمة نفسها.

يجعل esModuleInterop الاستيراد الافتراضي لحزم CommonJS يعمل (import express from "express"). وهو مفعّل دائمًا في TypeScript 7، وضبطه على false خطأ.

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

مشاركة الإعدادات باستخدام extends

يحمّل extends إعدادًا آخر ويتيح لهذا الملف تجاوز أجزاء منه:

{
    "extends": "./tsconfig.base.json",
    "compilerOptions": {
        "rootDir": "./src",
        "outDir": "./dist"
    },
    "include": ["src"]
}

تُدمج compilerOptions خيارًا بخيار، أما include وexclude وfiles من الملف الأساسي فتُستبدل ولا تُدمج إذا ضبطها هذا الملف. وتُحل المسارات في الملف الأساسي نسبةً إلى الملف الأساسي. يقبل extends حزمة أيضًا: ينشر مشروع @tsconfig/bases حزمة لكل بيئة، مثل npm install --save-dev @tsconfig/node24 ثم "extends": "@tsconfig/node24/tsconfig.json".

لرؤية الإعدادات النهائية بعد تطبيق كل extends والقيم الافتراضية، شغّل:

npx tsc --showConfig

الخيارات المحذوفة في TypeScript 7

أهملت TypeScript 6 هذه الإعدادات، وأزالتها TypeScript 7. الإعداد الذي ما زال يستخدم أحدها يفشل بالخطأ error TS5108 أو TS5102، مثل Option 'baseUrl' has been removed. Please remove it from your configuration.

الإعداد المحذوفالبديل
"target": "es5"es2015 أو ما بعده
"moduleResolution": "node" (node10) أو "classic"nodenext أو bundler
"module": "amd" و"umd" و"system" و"none"nodenext أو esnext أو preserve، وأداة تجميع للصيغ الأخرى
baseUrlمدخلات paths نسبةً إلى ملف tsconfig
outFileأداة تجميع
downlevelIterationلا شيء: الأهداف من es2015 فما فوق تدعم التكرار أصلًا
"esModuleInterop": false و"allowSyntheticDefaultImports": false و"alwaysStrict": falseاحذف السطر؛ هذه مفعّلة دائمًا

تسرد صفحة TypeScript 7 بقية التغييرات في ذلك الإصدار، ومنها القيم الافتراضية الجديدة التي لا يغطيها هذا الجدول.

الأسئلة الشائعة

ما هو ملف tsconfig.json؟

هو ملف إعدادات مشروع TypeScript. وجوده يجعل المجلد جذر المشروع، ويضبط compilerOptions طريقة فحص المترجم للكود وإخراجه، وتحدد include أو exclude أو files الملفات التي تنتمي إلى المشروع. تشغيل tsc دون وسائط يقرأ هذا الملف.

كيف أنشئ ملف tsconfig.json؟

شغّل npx tsc --init في مجلد المشروع (مع تثبيت TypeScript). يكتب ملف tsconfig.json بإعدادات موصى بها وتعليق على كل خيار. ويمكنك أيضًا كتابة الملف يدويًا؛ فالقيمة {} ملف tsconfig صحيح يستخدم كل القيم الافتراضية.

ما القيمة التي أضبط عليها target في tsconfig؟

أقدم إصدار JavaScript يجب أن يعمل عليه كودك. مع Node.js الحالي تكون es2022 أو ما بعدها آمنة؛ والقيمة الافتراضية في TypeScript 7 هي es2025. يتحكم target في الصياغة الأحدث التي يُعاد كتابتها للمحركات الأقدم، ويختار أيضًا lib الافتراضي، أي مجموعة الواجهات البرمجية المدمجة التي يعرفها الفاحص.

ما الفرق بين module و moduleResolution؟

يحدد module نوع كود الوحدات الذي يكتبه المترجم (import/export في ES أو require في CommonJS) وقواعد الوحدات المطبقة. أما moduleResolution فيحدد كيف يُعثر على مسار استيراد مثل "./utils.js" أو "lodash" على القرص. استخدم nodenext للكود الذي يشغّله Node.js، وmodule: "preserve" (الذي يعني ضمنيًا التحليل bundler) للكود الذي تعالجه أداة تجميع.

هل يمكن وضع تعليقات في tsconfig.json؟

نعم. يقرأ المترجم الملف كـ JSON مع تعليقات: يُسمح بتعليقات // و/* */ وبالفواصل الزائدة في النهاية، ولهذا يكتب tsc --init ملفًا مليئًا بالخيارات المعلّقة. أما الأدوات الأخرى التي تحلله كـ JSON صارم فقد تفشل بسببها.

Coddy programming languages illustration

تعلّم البرمجة مع Coddy

ابدأ الآن