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" يعمل مع حزم CommonJS | true (لا يمكن تعطيله) |
skipLibCheck | تخطي فحص أنواع ملفات .d.ts، ومنها ما في node_modules | false |
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 صارم فقد تفشل بسببها.