Menu

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.

לקוד ש-bundler כמו Vite, esbuild או webpack בונה, ה-bundler כותב את ה-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"]
}

תבניות הפתיחה של frameworks (Vite, Next.js, Angular) יוצרות tsconfig.json משלהן. התחילו מהקובץ שלהן במקום להחליף אותו.

האפשרויות החשובות

אפשרותמה היא עושהברירת מחדל ב-TypeScript 7
targetגרסת ה-JavaScript של הפלט; תחביר חדש נכתב מחדש עבור targets ישניםes2025
libטיפוסי ה-APIs המובנים שבודק הטיפוסים מכיר (Array.prototype.at, Map, document)תואם ל-target, ובנוסף ה-DOM
moduleסוג קוד המודולים שנוצר וכללי המודולים שחליםesnext
moduleResolutionאיך נתיבי import נמצאים בדיסקnodenext או node16 עם ה-module המתאים, אחרת bundler
strictמפעיל את כל משפחת הבדיקות הקפדניותtrue
rootDirהתיקייה שהמבנה שלה משוכפל לתוך outDirהתיקייה שמכילה את tsconfig.json
outDirלאן הולכים קובצי ה-.js (וה-.d.ts)ליד כל קובץ מקור
include / exclude / filesאילו קבצים הם חלק מהפרויקטכל קובץ .ts מתחת לתיקייה
typesאילו חבילות @types נטענות בלי import[], אף אחת
noEmitרק לבדוק, לא לכתוב כלוםfalse
declarationלכתוב גם קובצי הצהרת טיפוסים .d.tsfalse
sourceMapלכתוב קובצי .js.map עבור דיבאגריםfalse
esModuleInteropמאפשר ל-import x from "cjs-package" לעבוד עם חבילות CommonJStrue (אי אפשר לכבות)
skipLibCheckמדלג על בדיקת הטיפוסים של קובצי .d.ts, כולל אלה שב-node_modulesfalse

target ו-lib

target קובע על איזו גרסת JavaScript הפלט צריך לרוץ. תחביר חדש יותר מה-target נכתב מחדש: עם "target": "es2017", שדה של מחלקה או ??= הופכים לקוד ישן יותר. ה-target הנמוך ביותר ש-TypeScript 7 מקבל הוא es2015 (es6); es5 הוסר.

target לא מוסיף APIs חסרים של זמן ריצה. לתאר אותם זה התפקיד של 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 מחליט. imports יחסיים במודולי ES צריכים סיומת קובץ, שנכתבת .js למרות שהמקור הוא .ts: import { add } from "./math.js". moduleResolution מתאים את עצמו אוטומטית.
  • preserve: לקוד ש-bundler מעבד. ה-imports נשארים כמו שנכתבו, והרזולוציה משתמשת בכללי bundler, שמאפשרים imports בלי סיומת.
  • 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". עמוד המודולים מסביר בפירוט imports ו-exports.

strict ואפשרויות הבדיקה

"strict": true מפעיל קבוצה של בדיקות בבת אחת: noImplicitAny, strictNullChecks, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, strictBuiltinIteratorReturn, noImplicitThis ו-useUnknownInCatchVariables. זו ברירת המחדל ב-TypeScript 7, והיא מופעלת בכל דוגמה להרצה כאן. קוד שנכתב למצב strict מצמצם את הטיפוס לפני שהוא משתמש בערך שעלול להיות חסר:

בלי הערת טיפוס, אי אפשר להסיק את הטיפוס של פרמטר, ו-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 לבודק טיפוסים בלבד. השתמשו בזה כשכלי אחר (bundler, tsx, ה-type stripping של Node.js) מייצר את ה-JavaScript.
  • "declaration": true כותב קובץ .d.ts לכל מודול, הטיפוסים בלי הקוד. ספריות צריכות את זה כדי שלמשתמשים שלהן יהיו טיפוסים. declarationMap מוסיף מפות כדי ש-"go to definition" יוביל לקוד ה-.ts.
  • "sourceMap": true כותב קובצי .js.map כדי שדיבאגרים ו-stack traces יצביעו על השורות ב-.ts.
  • "noEmitOnError": true לא כותב כלום כל עוד יש שגיאות טיפוס. בלעדיו, tsc מדווח על השגיאות ועדיין כותב את ה-JavaScript.

types, esModuleInterop ו-skipLibCheck

types מפרט את חבילות ה-@types שנטענות באופן גלובלי, בלי import. ברירת המחדל של TypeScript 7 היא רשימה ריקה, ולכן אחרי npm install --save-dev @types/node מוסיפים גם "types": ["node"]; אחרת process ו-require נשארים לא מוכרים (error TS2591: Cannot find name 'process'). כלי הרצת בדיקות עם פונקציות גלובליות, כמו describe של Jest, נכנסים לאותה רשימה.

esModuleInterop גורם ל-default imports של חבילות CommonJS לעבוד (import express from "express"). הוא תמיד מופעל ב-TypeScript 7, והגדרתו ל-false היא שגיאה.

skipLibCheck מדלג על בדיקת הטיפוסים של קובצי הצהרה. הוא מאיץ builds ומונע שגיאות בתוך 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, ו-bundler לפורמטים אחרים
baseUrlרשומות paths יחסיות לקובץ ה-tsconfig
outFilebundler
downlevelIterationכלום: targets מ-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 שבברירת המחדל, אוסף ה-APIs המובנים שבודק הטיפוסים מכיר.

מה ההבדל בין module ל-moduleResolution?

module קובע איזה סוג קוד מודולים הקומפיילר כותב (import/export של ES או require של CommonJS) ואילו כללי מודולים חלים. moduleResolution קובע איך נתיב import כמו "./utils.js" או "lodash" נמצא בדיסק. השתמשו ב-nodenext לקוד ש-Node.js מריץ, וב-module: "preserve" (שמשמעותו רזולוציית bundler) לקוד ש-bundler מעבד.

אפשר לכתוב הערות ב-tsconfig.json?

כן. הקומפיילר קורא אותו כ-JSON עם הערות: הערות // ו-/* */ ופסיקים בסוף רשימה מותרים, ולכן tsc --init כותב קובץ מלא באפשרויות שהוכנסו להערה. כלים אחרים שקוראים אותו כ-JSON קפדני עלולים להיכשל עליהן.

איור של שפות התכנות ב-Coddy

ללמוד תכנות עם Coddy

להתחיל