Menu

איך מריצים קובץ TypeScript: tsc, Node.js, tsx, ts-node

חמש דרכים להריץ קובץ .ts: לקמפל עם tsc ולהריץ את ה-JavaScript, להריץ ישירות עם node file.ts (type stripping), להשתמש ב-tsx או ב-ts-node, או להשתמש ב-Deno וב-Bun. אילו מהן בודקות טיפוסים, איזה תחביר כל אחת תומכת, ובאיזו לבחור.

בדף הזה יש עורכים שאפשר להריץ - לערוך, להריץ ולראות את הפלט מיד.

אי אפשר להריץ קובץ TypeScript כמו שהוא, כי דפדפנים ומנועי JavaScript לא מבינים הערות טיפוס. משהו צריך להסיר את הטיפוסים קודם. המשהו הזה הוא הקומפיילר של TypeScript (tsc), שגם בודק את הטיפוסים, או כלי מהיר יותר שרק מסיר אותם. הדרך המהירה ביותר להריץ את הקוד בדף הזה היא כפתור ההרצה:

פלט:

[x] Install TypeScript
[ ] Run a .ts file

כל בלוק קוד שאפשר להריץ בתיעוד הזה עובד באותה דרך: הקוד נבדק על ידי TypeScript 7 כש-strict מופעל, והוא רץ רק אם אין שגיאות טיפוסים. לניסויים ארוכים יותר, עורך ה-TypeScript האונליין הוא אותו עורך בדף משלו. שאר הדף עוסק בהרצת קובצי .ts על המחשב שלכם.

האפשרויות במבט אחד

פקודהבודקת טיפוסיםצריכה שלב buildתומכת ב-enum, namespace, parameter properties
npx tsc ואז node dist/index.jsכןכןכן
node index.ts (Node.js 22.18+, 23.6+)לאלאלא
npx tsx index.tsלאלאכן
npx ts-node index.tsכןלאכן, אבל לא עם TypeScript 7
deno run index.tsלא (deno check כן)לאכן
bun index.tsלאלאכן

העמודה שמפתיעה אנשים היא הראשונה: רוב האפשרויות המהירות מריצות קוד שיש בו שגיאות טיפוסים. פרויקט טיפוסי מריץ קוד עם אחת מהן ומריץ tsc --noEmit בנפרד, בעורך וב-CI, כדי לתפוס את השגיאות.

לקמפל עם tsc ואז להריץ עם Node

זו הגישה שעובדת בכל מקום ובודקת הכול. כש-TypeScript מותקן בפרויקט ויש tsconfig.json שקובע "rootDir": "./src" ו-"outDir": "./dist":

npx tsc
node dist/index.js

tsc בודק את הטיפוסים בכל הקבצים, ואז כותב קובצי .js לתיקייה dist. לקובץ יחיד בלי פרויקט, העבירו את שם הקובץ. אז הוא משתמש באפשרויות ברירת המחדל וכותב index.js ליד index.ts:

npx tsc index.ts
node index.js

(אם בתיקייה יש tsconfig.json, tsc מסרב לשמות קבצים עם error TS5112; הריצו npx tsc רגיל, או הוסיפו --ignoreConfig.)

כברירת מחדל tsc עדיין כותב את ה-JavaScript כשיש שגיאות טיפוסים, כך ש-node יכול להריץ תוכנית שנכשלה בבדיקה. הוסיפו "noEmitOnError": true להגדרות כדי למנוע את זה, או שרשרו את הפקודות בסקריפט כך שהשלב השני ירוץ רק אם הראשון הצליח:

{
    "scripts": {
        "build": "tsc",
        "start": "tsc && node dist/index.js"
    }
}

בזמן פיתוח, npx tsc --watch מקמפל מחדש בכל שמירה.

הרצת TypeScript ישירות עם Node.js

גרסאות עדכניות של Node.js מריצות קובצי .ts בעצמן:

node index.ts

Node מסיר את הערות הטיפוס, מחליף אותן ברווחים כדי שמספרי השורות ב-stack traces עדיין יתאימו, ומריץ את מה שנשאר. זה מופעל כברירת מחדל מאז Node.js 23.6.0 ו-22.18.0, לא מדפיס אזהרה מאז 24.3.0 ו-22.18.0, וסומן כיציב ב-Node.js 24.12.0 וב-25.2.0. גרסאות קודמות שיש בהן את התכונה (22.6 עד 22.17, ו-23.0 עד 23.5) צריכות את הדגל: node --experimental-strip-types index.ts.

ארבעה כללים באים איתו:

  • אין בדיקת טיפוסים. קובץ עם const age: number = "forty" רץ ומדפיס forty.
  • רק תחביר שאפשר למחוק. כל דבר שצריך להפוך לקוד JavaScript, במקום להיעלם, נדחה: enum, בלוקי namespace עם קוד זמן ריצה, parameter properties בבנאי כמו constructor(private name: string), ו-aliases מסוג import x = require(). Node נעצר עם SyntaxError [ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX]: TypeScript enum is not supported in strip-only mode.
  • המערכת מתעלמת מ-tsconfig.json. לאפשרויות כמו paths או target אין השפעה.
  • ייבואים צריכים שמות קבצים אמיתיים. כתבו import { add } from "./math.ts", עם הסיומת, וסמנו ייבואים של טיפוסים בלבד עם type: import { add, type Pair } from "./math.ts". בלי type, Node מחפש export בזמן ריצה בשם Pair ונכשל עם SyntaxError: The requested module './math.ts' does not provide an export named 'Pair'.

שתי אפשרויות קומפיילר גורמות ל-tsc לאכוף את אותם כללים, כך שהעורך מזהיר אתכם לפני ש-Node עושה את זה: "erasableSyntaxOnly": true מדווח error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled. על enum, ו-"verbatimModuleSyntax": true מחייב את מילת המפתח type בייבואים של טיפוסים בלבד. כדי להמשיך לכתוב סיומות .ts בייבואים ועדיין לקמפל עם tsc, הוסיפו "rewriteRelativeImportExtensions": true, שהופך את ./math.ts ל-./math.js בפלט.

ל-Node.js 24 יש גם --experimental-transform-types, שמייצר קוד ל-enums ול-parameter properties במקום לדחות אותם. הוא מדפיס ExperimentalWarning, ו-Node.js 26 הסיר את הדגל, אז אל תבנו עליו.

הבלוק הזה משתמש בשתי תכונות ש-node index.ts דוחה. הוא רץ כאן כי העורך מקמפל אותו עם הקומפיילר של TypeScript, שמייצר JavaScript לשתיהן:

הגרסה שאפשר למחוק של אותו קוד משתמשת באובייקט const ובשדה רגיל, ש-Node יכול להריץ כמו שהם:

tsx

tsx מריץ קובץ TypeScript בשלב אחד, בלי הגדרות ובלי הגבלות על התחביר:

npm install --save-dev tsx
npx tsx index.ts
npx tsx watch index.ts   # rerun on every change

הוא ממיר את הקוד עם esbuild, ולכן enums, namespaces ו-parameter properties עובדים, וייבואים בלי סיומות נפתרים כמו ב-bundler. כמו ה-type stripping של Node, הוא לא בודק טיפוסים. זו הבחירה הנפוצה לסקריפטים, לשרתי פיתוח ולבדיקות בגרסאות Node.js שקודמות ל-type stripping, או כשהקוד משתמש בתחביר ש-Node דוחה.

ts-node

ts-node היה במשך שנים הדרך הסטנדרטית להריץ TypeScript על Node.js, והוא עדיין מה שמדריכים רבים ופרויקטים ישנים משתמשים בו (npx ts-node index.ts, node -r ts-node/register). הוא בודק טיפוסים כברירת מחדל, בעזרת ה-API של JavaScript של הקומפיילר של TypeScript.

ה-API הזה הוא בדיוק מה ש-TypeScript 7 לא מספק: הקומפיילר שלו הוא תוכנה native, והחבילה typescript 7 לא חושפת ל-JavaScript שום API של קומפיילר. כש-TypeScript 7 מותקן, ts-node קורס לפני שהוא מריץ משהו:

TypeError: Cannot read properties of undefined (reading 'fileExists')
    at readConfig (/project/node_modules/ts-node/dist/configuration.js:91:33)

הגרסה האחרונה של ts-node, 10.9.2, היא מדצמבר 2023. לקוד חדש השתמשו ב-tsx או ב-node index.ts. הגדרה קיימת שתלויה ב-ts-node ממשיכה לעבוד אם הפרויקט נשאר על TypeScript 6 (npm install --save-dev typescript@6) ויש לו tsconfig.json, אפילו {} ריק. בלעדיו, ts-node חוזר לברירות מחדל מובנות שכוללות את ה-module resolution מסוג node10 ש-TypeScript 6 הוציא משימוש, ו-npx ts-node index.ts יוצא בלי להריץ את הקובץ ובלי להדפיס שגיאה.

Deno ו-Bun

שתי סביבות הריצה מתייחסות ל-TypeScript כסוג קובץ מן המניין:

deno run index.ts    # runs without checking
deno check index.ts  # type-checks, reports errors, runs nothing

bun index.ts         # runs without checking

אף אחת מהן לא צריכה ש-typescript יהיה מותקן או tsconfig.json, ושתיהן תומכות ב-enum ובשאר התכונות שאי אפשר למחוק. Deno כוללת עותק משלה של הקומפיילר של TypeScript בשביל deno check. Bun רק מסירה טיפוסים, ולכן בפרויקט Bun עדיין מתקינים typescript ומריצים tsc --noEmit כדי למצוא שגיאות טיפוסים.

שגיאות טיפוסים עוצרות את התוכנית רק עם tsc

רק הדרכים שמריצות tsc קודם מסרבות להריץ תוכנית עם שגיאות טיפוסים. העורך בדף הזה הוא אחת מהן, ולכן הבלוק הזה נעצר אצל הקומפיילר:

index.ts(6,21): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.

אם שומרים אותו קוד כקובץ ומריצים עם node index.ts, npx tsx index.ts או bun index.ts, הוא רץ ומדפיס 12, כי 3 * "4" ממיר את המחרוזת. זו הסיבה להשאיר את tsc --noEmit בתהליך גם כשכלי מהיר יותר מריץ את הקוד:

{
    "scripts": {
        "dev": "tsx watch src/index.ts",
        "typecheck": "tsc --noEmit"
    }
}

במה כדאי להשתמש?

  • למידה, או בדיקה מהירה: כפתור ההרצה בדפים האלה, או העורך האונליין.
  • סקריפט או כלי קטן על Node.js עדכני: node index.ts, עם erasableSyntaxOnly בהגדרות כדי שהעורך יסמן כל דבר ש-Node היה דוחה.
  • כל פרויקט Node.js, כל תחביר: tsx להרצה, tsc --noEmit לבדיקה.
  • ספרייה או כל דבר שאתם מפרסמים: tsc, כי הוא גם כותב את קובצי ה-.d.ts שהמשתמשים שלכם צריכים.
  • קוד front end: ה-bundler או ה-framework שלכם (Vite, Next.js, Angular CLI) מריצים את ה-TypeScript בשבילכם; הוסיפו tsc --noEmit לבדיקה.

שאלות נפוצות

איך מריצים קובץ TypeScript?

הדרך הקלאסית היא בשני שלבים: npx tsc מקמפל .ts ל-.js, ואז node dist/index.js מריץ את הפלט. ב-Node.js 22.18 או 23.6 ואילך אפשר גם להריץ node index.ts ישירות, כל עוד הקובץ משתמש רק בתחביר טיפוסים שאפשר למחוק. npx tsx index.ts מריץ כל קובץ TypeScript בשלב אחד.

האם Node.js יכול להריץ TypeScript ישירות?

כן. מאז Node.js 23.6 ו-22.18, node file.ts עובד בלי דגלים: Node מסיר את הערות הטיפוס ומריץ את השאר. הוא לא בודק טיפוסים, מתעלם מ-tsconfig.json, ודוחה תחביר שדורש יצירת קוד, כמו enum, namespace עם קוד זמן ריצה ו-parameter properties בבנאי.

האם ts-node עובד עם TypeScript 7?

לא. ts-node קורא ל-API של JavaScript של הקומפיילר, שהחבילה typescript 7 לא מספקת, ולכן הוא קורס בהפעלה (Cannot read properties of undefined (reading 'fileExists')). הגרסה האחרונה שלו היא 10.9.2 מדצמבר 2023. השתמשו ב-tsx, ב-type stripping של Node עצמו, או השאירו את ts-node עם TypeScript 6.

מה ההבדל בין tsx ל-ts-node?

tsx רק מסיר טיפוסים (עם esbuild) ומריץ את התוצאה, ולכן הוא עולה מהר ואף פעם לא מדווח על שגיאות טיפוסים. ts-node בודק טיפוסים כברירת מחדל בעזרת הקומפיילר של TypeScript, מה שהופך אותו לאיטי יותר וקושר אותו ל-API של JavaScript של הקומפיילר. רוב הפרויקטים היום משלבים tsx או node file.ts להרצה עם tsc --noEmit לבדיקה.

האם יש sandbox של TypeScript אונליין?

כן. בלוקי הקוד בדפי התיעוד האלה ועורך ה-TypeScript האונליין של Coddy מקמפלים את הקוד שלכם עם TypeScript 7 ומריצים אותו, ומציגים שגיאות קומפילציה או את הפלט של התוכנית. ה-TypeScript Playground הרשמי ב-typescriptlang.org מציג את ה-JavaScript שנוצר ואת השגיאות.

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

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

להתחיל