Съдържание на курса

Урок 1 — Инсталиране на TypeScript на твоя Linux Mint

От Dorian Chávez · основател на Hábil и архитект на интеграции ·

Време: 2 × 45 мин

Какво изграждаш: средата и първата ти програма

Какво научаваш: Node LTS, мениджър на пакети, tsc, редактор, строг tsconfig, изпълнение и дебъгване

След урока ще можеш да

  • Инсталираш и провериш Node.js 24 LTS, npm и компилатора на TypeScript на Linux Mint.
  • Създадеш ESM проект с package.json, локална зависимост от TypeScript и възпроизводим заключващ файл.
  • Компилираш програма с npx tsc --strict --target ES2022 --module nodenext и изпълниш получения JavaScript с Node.
  • Настроиш проект със строг tsconfig.json, изход в dist/ и карти на изходния код.
  • Разграничаваш изпълнението на .ts с премахването на типове на Node от проверката и компилирането му с tsc.
  • Отвориш проекта в редактор, спреш изпълнението с точка на прекъсване и поправиш диагностика TSxxxx.

Защо, преди как

revisor ще стане приложение с две части, които трябва да съвпадат: API, което пита няколко услуги, и уеб табло, което представя отчета. Преди да стигнем до тази сложност, трябва да отговорим на един по-малко ефектен, но решаващ въпрос: как компютърът ти превръща кода, който пишеш, в програма, която може да се изпълни?

JavaScript вече отговаря на част от този въпрос. Node изпълнява файлове .js; разбира синтаксиса на JavaScript, създава процеса, зарежда модули, дава достъп до файлове и мрежа и завършва процеса, когато работата приключи. От Node 22.18 може да изпълнява и определени файлове .ts, като изтрива синтаксиса им за типове. TypeScript добавя друг, отделен етап: tsc проверява програмата и произвежда JavaScript. Не замества Node и не се превръща в друга операционна система. Това е инструментът, който намира противоречия в кода ти, преди Node да има възможност да го пусне.

Това разделение има значение от първия ден. Представи си, че след няколко урока revisor получава списък от услуги и всеки елемент има нужда от име, URL и политика за таймаут. Ако объркаш число с текст или извикаш свойство, което не съществува, по-добре е да получиш обяснение при компилация, отколкото да го откриеш след внедряването на API. Компилаторът не проверява дали един URL наистина отговаря и не може да гарантира, че външен JSON има очакваната форма; тези граници ще се валидират по-нататък. Но може да провери дали кодът, който си написал, е последователен спрямо правилата, които сам си декларирал.

В Go go run събира компилацията и изпълнението в една команда и може да създаде впечатление, че двете са една и съща операция. TypeScript прави границата по-видима: tsc преобразува и проверява; node изпълнява. В началото изглеждат като две излишни стъпки. На практика са две различни отговорности и е добре да знаеш коя е сгрешила. Ако tsc съобщи TS2322, още няма надеждна програма, която да се пусне. Ако tsc завърши без съобщения, а Node се провали, проблемът е в поведението при изпълнение, в импорт, който не съществува на диска, в променлива на средата или във външен отговор.

Правилният инструмент също предотвратява проблеми, които се появяват късно. Linux Mint 22.x наследява основата на Ubuntu 24.04 и пакетите му дават предимство на стабилността; LMDE, от своя страна, се основава на Debian. Това е разумно за системни компоненти, но един курс се нуждае от изрично зададена линия на Node и версия на TypeScript. Тук ще използваш Node 24 LTS и TypeScript 7.0.2. Не е нужно да помниш второстепенна ревизия на Node или определена версия на npm: провери, че node -v започва с v24, че npm отговаря и че локалният компилатор отпечатва Version 7.0.2.

Първото решение в курса е да инсталираш TypeScript вътре в проекта, а не като глобален инструмент на твоя потребител. Глобалната инсталация отговаря на въпроса „какъв компилатор имам днес на този лаптоп?“. Локалната зависимост отговаря на по-полезен въпрос: „с какъв компилатор трябва да се изгражда този проект, тук и на друг компютър?“. package.json пази това решение; package-lock.json записва разрешените версии. Така, когато друг човек клонира revisor, не зависи от това, което случайно е инсталирано при него.

Ще започнем и с ESM, стандартните модули на JavaScript. Така избягваме да приемем стар синтаксис на модули само защото още се появява в остарели примери. В revisor, package.json декларира "type": "module", а относителните импорти пишат разширението, което файлът ще има при изпълнение: .js, макар изходният файл да е .ts. Първия път изглежда странно, но е пряка последица от факта, че tsc издава JavaScript и Node го зарежда от dist/.

Накрая, включването на strict не е церемония. Това е избор компилаторът да сочи несигурностите, докато проектът е малък. Ако започнеш отпуснато и затегнеш правилата, след като имаш двайсет файла, диагностиките се трупат и трудно се различава дизайнерско решение от механична поправка. revisor ще има услуги, които се провалят, липсващи отговори и външни данни; ако го изграждаш със строга проверка от първия ред, тези възможности стават видими, вместо да бъдат скрити.

Понятията

Node.js, npm и локалната зависимост

Node.js е средата, която ще изпълнява JavaScript на revisor. npm е мениджърът на пакети, включен в Node: изтегля зависимости, запазва версиите им и предлага команди, дефинирани от проекта. TypeScript е една от тези зависимости за разработка: нужна е, за да се преобразува изходният код, но не и за да се изпълни вече компилираният JavaScript.

Първо инсталирай Node 24 LTS. nvm е мениджър на версии на Node: позволява да инсталираш и избираш линии на Node, без да използваш системния пакет. Официалната документация на nvm публикува този инсталатор за версия 0.40.8:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.8/install.sh | bash

Отвори нов терминал след инсталацията. Ако терминалът ти използва bash и още не намира командата, зареди конфигурацията му с source ~/.bashrc; инсталаторът променя подходящия стартов файл измежду .bashrc, .bash_profile, .zshrc и .profile. Сега инсталирай и избери линия 24:

nvm install 24
nvm alias default 24
nvm use 24
nvm --version
node -v
npm -v

nvm --version и npm -v трябва да отпечатат версия. node -v трябва да започва с v24; nvm install 24 може да избере по-нова второстепенна ревизия в рамките на тази LTS линия. Ако nvm казва, че не съществува, отвори нов терминал или зареди стартовия файл, който инсталаторът е посочил. Преди да търсиш решения напосоки, изпълни echo "$SHELL", за да разбереш дали използваш bash, zsh или друг шел; промяна, направена в .bashrc, не се зарежда автоматично в сесия на zsh. В Linux Mint, ако още нямаш curl, инсталирай го с sudo apt install curl и повтори командата на инсталатора.

Създай сега папка за проекта. Името няма специално техническо значение засега: ще бъде коренът на revisor, където ще живеят package.json, tsconfig.json, изходният код и компилираният изход.

mkdir -p ~/proyectos/revisor/src
cd ~/proyectos/revisor
npm init -y
npm install --save-dev --save-exact typescript@7.0.2 @types/node@24

npm init -y създава основен package.json. npm install --save-dev добавя инструментите, нужни за разработка, записва версиите им в package.json и генерира package-lock.json. --save-exact не позволява на npm да запише префикса ^: проектът запазва точно TypeScript 7.0.2 и ревизията на @types/node, която е била разрешена в линия 24. Флагът --save-dev изразява, че TypeScript и декларациите на Node са необходими за изграждането и проверката на проекта, а не за изпълнението на крайния резултат в продукция.

Нагласи файла package.json, за да декларира ESM и да даде полезни имена на командите на проекта:

{
  "name": "revisor",
  "private": true,
  "type": "module",
  "scripts": {
    "compilar": "tsc",
    "verificar": "tsc --noEmit",
    "arrancar": "node dist/main.js"
  },
  "devDependencies": {
    "@types/node": "24.19.1",
    "typescript": "7.0.2"
  }
}

"private": true предотвратява случайна публикация в публичния регистър на npm. "type": "module" кара Node да интерпретира файловете .js на проекта като ESM модули. Командите под "scripts" се изпълняват с npm run compilar, npm run verificar и npm run arrancar; npm автоматично намира инсталираните изпълними файлове в node_modules/.bin/, така че не е нужно да добавяш тази папка в PATH. Точната ревизия на @types/node може да е друга от линия 24, ако инсталираш курса по-късно; запази тази, която е записала твоята инсталация с --save-exact.

Като минимален пример тази програма само потвърждава, че компилаторът и Node са съгласувани. Първият ред идентифицира файла на фигурата; не е част от синтаксиса, необходим за твоя проект.

// fig01_01.ts
const nombrePrograma = "revisor";

console.log(`Hola, ${nombrePrograma}: TypeScript ya compila.`);
$ npx tsc --strict --target ES2022 --module nodenext fig01_01.ts
$ node fig01_01.js
Hola, revisor: TypeScript ya compila.

В revisor същата идея се появява в по-голям мащаб. Локалната зависимост позволява npm run compilar да използва компилатора, договорен от проекта, а не глобална версия, която някой е инсталирал преди месеци. Пази package-lock.json в Git заедно с package.json: първият не е генерирано боклуче, а точният запис на пакетите, които npm е разрешил. За разлика от него, node_modules/ се изключва с .gitignore, защото може да се възстанови с npm install от тези два файла.

Често срещано объркване е да се мисли, че npx tsc инсталира TypeScript глобално. Не е така, когато пакетът вече е в проекта: npx първо намира локалния изпълним файл. Можеш да провериш коя версия е свързана с проекта с тази команда:

npx tsc --version

Трябва да отговори Version 7.0.2. Ако отговори друга версия, не продължавай, сякаш нищо не е станало. Провери дали си вътре в ~/proyectos/revisor, дали node_modules/ съществува и дали package.json има правилната зависимост. Името на инструмента, tsc, се запазва, макар сегашната му имплементация да е нативна; не е нужно да променяш командите на курса заради това.

Фигурите на курса също се нуждаят от собствен ESM контекст и локален компилатор. Създай папка, съседна на проекта, за да експериментираш, без да смесваш генерираните JavaScript файлове със src/:

mkdir -p ~/proyectos/figuras
cd ~/proyectos/figuras
npm init -y
npm install --save-dev --save-exact typescript@7.0.2 @types/node@24

Отвори нейния package.json и добави "type": "module" (и "private": true) до това, което npm е написал, без да триеш devDependencies: ако ги загубиш, TypeScript вече не е инсталиран. Номерът на @types/node може да е друг от линия 24. Не слагай tsconfig.json в тази папка: фигурите от един файл използват изрично зададените си опции с npx tsc. Когато някоя използва await на най-високо ниво, този ESM package.json предотвратява TS1309. npx tsc първо търси изпълнимия файл в локалната ~/proyectos/figuras/node_modules/.bin/; не инсталира TypeScript глобално.

{
  "name": "figuras",
  "private": true,
  "type": "module",
  "devDependencies": {
    "@types/node": "24.19.1",
    "typescript": "7.0.2"
  }
}

Компилиране, издаване и изпълнение

Node 24 може да изпълни .ts директно чрез type stripping, премахване на синтаксиса за типове преди изпълнението на JavaScript. Тази възможност е налична без флаг от Node 22.18 и е стабилна от Node 24.12. Това не е компилация: Node заменя типовете с интервали и не проверява типове. Затова node src/main.ts може да е полезно за скрипт от един файл, но не доказва, че програмата е правилна; tsc е този, който проверява и издава изхода, който revisor ще изпълнява.

Премахването на типове приема само изтриваем синтаксис. Node не допуска .tsx, нито конструкции, които генерират JavaScript, като enum, namespace със стойности или свойства на параметри в конструктори, освен ако не активираш експерименталния --experimental-transform-types. Не чете и tsconfig.json, paths, нито файлове .ts вътре в node_modules. Ако импортираш само тип, запиши го с import type, за да съвпада с това, което Node може да изтрие. erasableSyntaxOnly е опция на TypeScript, която предупреждава за конструкции, които Node не може да изтрие.

Импортите показват защо потокът на курса компилира проектите, преди да ги стартира. При директно изпълнение на .ts Node изисква буквалното разширение на източника: import "./arranque.ts" работи; import "./arranque.js" търси именно файл .js до източника и се проваля, ако съществува само arranque.ts. revisor използва .js в импортите си, защото това ще бъде пътят на издадените файлове в dist/. Затова използвай node archivo.ts само за експеримент с един файл, а npm run compilar, следвано от npm run arrancar, за проекта от няколко файла.

tsc чете програмата, проверява я и издава .js. Това преобразуване понякога се нарича транспилиране, защото източникът и резултатът са близки езици, но за ежедневната ти работа е достатъчно да помниш два глагола: проверявай и компилирай с tsc; изпълнявай изхода с node.

Разгледай тази програма. Анотацията : string служи, за да провери TypeScript стойността на estado; не е предназначена да стига до Node. Типовете ще се изучат в дълбочина в следващия урок. Засега използвай я като доказателство, че компилаторът проверява слой, който не е част от изпълнимата програма.

// fig01_02.ts
const estado: string = "entorno listo";
const serviciosPendientes = 3;

console.log(`revisor: ${estado}; ${serviciosPendientes} servicios pendientes.`);
$ npx tsc --strict --target ES2022 --module nodenext fig01_02.ts
$ node fig01_02.js
revisor: entorno listo; 3 servicios pendientes.

След компилацията отвори fig01_02.js. Ще видиш, че съдържа const estado = "entorno listo";, без : string. TypeScript изтрива анотациите на типовете, когато издава JavaScript. Това е важна разлика спрямо Go: Go компилира в бинарен файл, който носи машинни инструкции; TypeScript издава JavaScript и изисква Node, браузър или друга JavaScript среда да изпълни този резултат.

Това установява и ясна граница. Ако някой промени издадения JavaScript файл или ако клиент изпрати JSON с фалшиви данни, анотациите на TypeScript няма да се появят по време на изпълнението, за да ги спрат. Типовете защитават кода, който компилираш; не валидират сами по себе си това, което идва от мрежата. В урока за външните данни revisor ще валидира изрично границите си, преди да превърне непозната информация в надеждни стойности.

Не изпълнявай файловете, които TypeScript оставя до изходния код, в реален проект. При фигурите е полезно, защото намалява стъпките, но смесването на .ts и .js в src/ накрая обърква кой файл трябва да се редактира и кой да се публикува. revisor ще раздели източниците от изхода: src/ ще съдържа това, което пишеш; dist/ ще съдържа това, което произвежда tsc.

Вътре в проекта началната стартова програма може да е нарочно малка. Не декларирай още Servicio и Estado: тези имена ще получат точен модел в урок 3. На този етап правилният напредък е да имаш проект, който се изгражда повторяемо, а не да изпреварваш типове, които още нямат ясни правила.

Връзката между командите на проекта винаги ще е една и съща:

npm run compilar
npm run arrancar

Първата проверява проекта и произвежда файловете под dist/. Втората изпълнява точно изградения изход. Ако редактираш src/main.ts и забравиш да компилираш отново, npm run arrancar ще изпълни предишната версия на dist/main.js. Това разделение изглежда неудобно, докато не дебъгваш повреда: знаеш дали гледаш текущия код или стар артефакт.

tsconfig.json и строгият режим

Да записваш всички опции за компилация във всяка команда върши работа за една фигура, но не за проект. tsconfig.json е договорът за компилация: идентифицира изходните файлове, определя изхода и запазва решения, които трябва да са еднакви за всеки участник в проекта и за непрекъснатата интеграция.

Създай този tsconfig.json в корена на revisor/:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "rootDir": "./src",
    "outDir": "./dist",
    "strict": true,
    "types": ["node"],
    "sourceMap": true,
    "noEmitOnError": true
  },
  "include": ["src"]
}

target декларира версията на JavaScript, която TypeScript ще издава. ES2022 е подходяща за Node 24: не задължава компилатора да преобразува модерни възможности в по-дълги еквиваленти. module и moduleResolution със NodeNext карат TypeScript да следва правилата за модули, които Node прилага към модерен проект. Двойката е важна: изборът на друго разрешаване може да допусне импорти, които после Node няма да може да разреши.

rootDir и outDir правят видима границата между това, което пишеш, и това, което се генерира. Фиксираната входна точка на курса, src/main.ts, завършва като dist/main.js; папка src/reporte/tabla.ts завършва като dist/reporte/tabla.js. Това съответствие по-нататък ще позволи на бекенда да публикува чиста директория, без смесени източници и зависимости за разработка.

strict: true активира семейство проверки, между които strictNullChecks, noImplicitAny и проверки за инициализация и функции. От TypeScript 6 стойността по подразбиране вече е true; изписването ѝ прави явно решение, което този, който го изключи, трябва да промени нарочно. Не означава „TypeScript става досаден“; означава, че компилаторът спира да предполага, че всяка стойност съществува, че всяка променлива има очевидна форма или че двусмислени данни са безопасни. В бъдеще можеш да активираш още по-взискателни опции, но strict е непреговарящата се отправна точка на курса.

types: ["node"] казва на TypeScript да зареди декларациите на типове на Node, инсталирани чрез @types/node, включително тези на модули като node:fs/promises. От TypeScript 6 опцията types вече не зарежда по подразбиране всички инсталирани пакети @types, така че декларирането ѝ е необходимо, дори @types/node да е в devDependencies: без нея импорт от Node може да се провали с TS2591.

noEmitOnError не позволява да остане нов JavaScript, когато проектът има грешки. Без тази опция е възможно TypeScript да намери противоречие и въпреки това да издаде файлове; после изпълняваш частично обновен dist/ и диагностицираш погрешния проблем. В проект със услуги е за предпочитане да се произвежда познат и пълен изход, отколкото съмнителен изход.

sourceMap: true създава карти, които свързват всеки издаден JavaScript файл с неговия TypeScript източник. Сами по себе си не променят поведението в продукция. Полезността им личи при дебъгване: редакторът може да спре на реда от .ts, който си написал, вместо да те изпрати на ред от издаден JavaScript, който не съдържа оригиналните анотации.

В revisor първият src/main.ts може да използва повторно модела от предишната фигура. Копирай го в src/main.ts, изпълни npm run compilar и провери дали се появява dist/main.js заедно с dist/main.js.map. От този момент не е нужно да повтаряш дълги флагове: npm run compilar взема решенията си от tsconfig.json.

Има нюанс, който предотвратява много объркване: с TypeScript 7.0.2, ако изпълниш npx tsc src/main.ts в папка, която съдържа tsconfig.json, компилаторът не го игнорира: спира с TS5112 и те моли да избереш. За да компилираш изолиран файл, използвай npx tsc --ignoreConfig src/main.ts и подай флаговете, които ти трябват; за да компилираш проекта според конфигурацията му, използвай npx tsc без файлове или npx tsc --project tsconfig.json. В този курс npm run compilar е равностойно на втория случай, защото скриптът съдържа само tsc.

Този минимален проект показва и двете решения. Първата команда се проваля, защото е посочен файл, докато съществува tsconfig.json; втората чете цялата конфигурация, а третата изпълнява издадения JavaScript.

{
  "name": "revisor",
  "private": true,
  "type": "module",
  "scripts": {
    "compilar": "tsc",
    "verificar": "tsc --noEmit",
    "arrancar": "node dist/main.js"
  }
}
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "rootDir": "./src",
    "outDir": "./dist",
    "strict": true,
    "types": ["node"],
    "sourceMap": true
  },
  "include": ["src"]
}
// fig01_05/src/main.ts
const estado: string = "entorno listo";

console.log(`revisor: ${estado}`);
$ cd fig01_05
$ npx tsc src/main.ts
error TS5112: tsconfig.json is present but will not be loaded if files are specified on commandline. Use '--ignoreConfig' to skip this error.
$ npx tsc --project tsconfig.json
$ node dist/main.js
revisor: entorno listo

ESM модули и разширения .js

Модулът позволява програмата да се разпредели във файлове, които експортират стойности, и файлове, които ги импортират. revisor ще има нужда от това разделение: споделеният модел, логиката, която пита услугите, сървърът и таблото не бива да живеят в един безкраен файл. ESM е стандартната система за модули на JavaScript и тя ще използваме оттук нататък.

Първата изненада е, че файл на TypeScript импортира разширението .js. Не е правописна грешка. TypeScript вижда ./arranque.js, разбира, че съответният източник е arranque.ts, и издава import "./arranque.js", който Node може да разреши при изпълнение вътре в dist/.

// fig01_03/arranque.ts
export function mensajeDeArranque(): string {
  return "revisor: entorno listo";
}
// fig01_03.ts
import { mensajeDeArranque } from "./fig01_03/arranque.js";

console.log(mensajeDeArranque());
$ npx tsc --strict --target ES2022 --module nodenext fig01_03.ts
$ node fig01_03.js
revisor: entorno listo

Примерът има два файла нарочно. arranque.ts предлага функция с export; главният файл я получава чрез import. В ESM проект не пиши require, не пропускай разширението в относителните импорти и не сменяй .js с .ts само защото четеш източника. Тези три решения смесват правила от различни епохи и обикновено водят до грешки, които изглеждат като проблеми на компилатора, а всъщност са правила за зареждане на Node.

В revisor този модел ще позволи ясна граница. По-нататък src/modelo/servicio.ts ще експортира споделения речник; src/revisar/ ще използва този речник, за да пита; а таблото ще импортира същите компилирани или публикувани договори от споделен пакет. Днес е достатъчно да упражниш механиката: един файл експортира, друг импортира, а Node изпълнява изхода .js.

Не използвай абсолютни пътища на диска като импорти, нито измислени псевдоними от първия урок. Псевдоним като @/modelo може да е удобен в редактора, но изисква едновременно да се настроят TypeScript, Node, тестовете и уеб пакетиращият инструмент. Явните относителни импорти са по-малко впечатляващи и по-прозрачни, докато учиш кой файл от кой зависи.

Редактор, диагностика и дебъгване

Можеш да пишеш TypeScript във всеки текстов редактор, но редактор с поддръжка на езика намалява времето между допускането на грешка и разбирането ѝ. Visual Studio Code разпознава tsconfig.json, показва диагностиките на TypeScript, позволява да отидеш до дефиниция и дебъгва Node. Отвори цялата папка на проекта, а не само src/main.ts, за да открие редакторът package.json, tsconfig.json и структурата на модулите.

В Linux Mint 22.x можеш да изтеглиш пакета .deb за Debian/Ubuntu от страницата за изтегляне на VS Code и, от папката, където си го запазил, да го инсталираш така. Пакетът предлага да настрои хранилището на Microsoft, за да получаваш автоматични обновявания:

sudo apt install ./<archivo>.deb
code --version

Можеш да настроиш това хранилище и ръчно. Списъкът с архитектури е този, който публикува Microsoft: amd64, arm64 и armhf.

sudo apt install wget gpg
wget -qO- https://packages.microsoft.com/keys/microsoft.asc | sudo gpg --dearmor -o /usr/share/keyrings/microsoft.gpg
sudo tee /etc/apt/sources.list.d/vscode.sources > /dev/null <<'EOF'
Types: deb
URIs: https://packages.microsoft.com/repos/code
Suites: stable
Components: main
Architectures: amd64,arm64,armhf
Signed-By: /usr/share/keyrings/microsoft.gpg
EOF
sudo apt update
sudo apt install code
code --version

Това са процедури за инсталиране в системата: прочети ги и ги изпълни в твоя Mint, а не вътре в проекта. За LMDE използвай изтегления пакет .deb; не предполагай, че източниците му на пакети са тези на Ubuntu.

cd ~/proyectos/revisor
code .

Терминалът не се нуждае от командата code, за да работи TypeScript. Ако инсталацията ти на Visual Studio Code не я е добавила в PATH, отвори приложението от менюто и използвай „Open Folder“, за да избереш ~/proyectos/revisor. Важното е да отвориш корена на проекта, защото там е конфигурационният файл, който определя как се проверяват изходните файлове.

Настрой дебъгването така, че първо да компилира със скрипта на проекта. Създай папката .vscode/ и запази тези два валидни JSON файла. Задачата (task) е инструкция, която VS Code може да изпълни, преди да стартира дебъгера.

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "compilar revisor",
      "type": "shell",
      "command": "npm",
      "args": ["run", "compilar"],
      "problemMatcher": "$tsc"
    }
  ]
}

Запази го като .vscode/tasks.json. Сега създай .vscode/launch.json:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Depurar revisor",
      "type": "node",
      "request": "launch",
      "program": "${workspaceFolder}/dist/main.js",
      "outFiles": ["${workspaceFolder}/dist/**/*.js"],
      "preLaunchTask": "compilar revisor",
      "console": "integratedTerminal",
      "skipFiles": ["<node_internals>/**"]
    }
  ]
}

preLaunchTask свързва двете конфигурации: преди да изпълни Node, VS Code пуска npm run compilar; не използва задача на TypeScript, инсталирана от редактора, която може да сочи към друга версия. outFiles показва къде са JavaScript файловете и картите, които съответстват на TypeScript източника.

Компилирай преди дебъгване, ако искаш да провериш резултата отделно:

npm run compilar

После отвори src/main.ts, щракни вляво от номера на ред с console.log, за да поставиш червена точка, и натисни F5. Избери конфигурацията „Depurar revisor“. Благодарение на sourceMap: true дебъгерът трябва да спре на оригиналния ред от TypeScript. Оттам можеш да инспектираш променливи, да напредваш с един ред, да влезеш във функция или да продължиш.

Като бърза алтернатива отвори палитрата с команди, избери „Debug: Create JavaScript Debug Terminal“ и пусни node dist/main.js в този терминал. Този режим дебъгва всеки процес на Node, който стартираш там; при активни карти на изходния код точките на прекъсване се поставят в .ts. launch.json е по-добър, когато искаш да повтаряш едно и също стартиране с F5; терминалът за дебъгване служи за проучване на конкретна команда.

Точката на прекъсване не оправя програмата и не замества тест. Служи да наблюдаваш реалното състояние точно преди дадена операция. По-нататък ще бъде полезна, за да спреш revisor преди да интерпретира HTTP отговор и да сравниш това, което си предполагал, че е пристигнало, със стойността, която наистина е пристигнала. Ако една стойност може да е undefined, не приемай, че дебъгерът доказва, че винаги ще е така само защото при конкретно изпълнение е имала стойност; използвай го, за да формулираш обяснение, а после напиши валидация или възпроизводим тест.

Конзолата на редактора и терминалът изпълняват различни роли. Диагностиките TSxxxx ти казват, че програмата противоречи на типовете си преди изпълнението. Конзолата за дебъгване показва какво се е случило при конкретно изпълнение. И двете са ценни, но отговарят на различни въпроси. Да започнеш с диагностиката на компилатора обикновено спестява време: няма смисъл да преследваш в дебъгера клон на програма, за която TypeScript вече знае, че не може да бъде построена правилно.

Грешката, която ще видиш

Следващата програма има умишлена грешка. TypeScript 7.0.2 я отхвърля, преди да издаде JavaScript: limite е декларирана като число, но написаната стойност е текст.

// fig01_04.ts
const limite: number = "30";

console.log(limite);
$ npx tsc --strict --target ES2022 --module nodenext fig01_04.ts
fig01_04.ts(2,7): error TS2322: Type 'string' is not assignable to type 'number'.

TS2322 означава, че си се опитал да присвоиш стойност от един тип на място, което изисква друг. Не се поправя с заглушаване на компилатора или с превръщане на всичко в any. Първо реши какво е било намерението. Ако лимитът представлява секунди, правилната стойност може да е 30 без кавички. Ако данните са дошли като текст от променлива на средата, ще трябва да ги валидираш и преобразуваш на границата; тази ситуация ще се разгледа в урок 6.

Има още една честа диагностика в началото на ESM проект. Ако напишеш относителен импорт без разширение:

import { mensajeDeArranque } from "./arranque";

с moduleResolution: "NodeNext" TypeScript 7.0.2 съобщава това:

$ npx tsc
src/main.ts(1,35): error TS2835: Relative import paths need explicit file extensions in ECMAScript imports when '--moduleResolution' is 'node16' or 'nodenext'. Did you mean './arranque.js'?

TS2835 не иска да превърнеш изходния файл в JavaScript. Иска да напишеш пътя, който Node ще види след компилацията: ./arranque.js. TypeScript ще свърже този път с arranque.ts по време на компилацията. Детайлът не позволява на tsc да приеме импорт, който Node не би могъл да намери при изпълнение на dist/main.js.

Две близки грешки изразяват различни проблеми. TS2307 означава, че TypeScript не намира посочения модул; например ако не съществува src/arranque.ts:

$ npx tsc
src/main.ts(1,35): error TS2307: Cannot find module './arranque.js' or its corresponding type declarations.

TS2305 е различна: файлът съществува, но не експортира поисканото име. Ако arranque.ts не експортира mensajeDeArranque, импортът води до тази диагностика:

$ npx tsc
src/main.ts(1,10): error TS2305: Module '"./arranque.js"' has no exported member 'mensajeDeArranque'.

Преди да преинсталираш пакети, провери конкретното: дали съществува src/arranque.ts, дали пътят е относителен спрямо src/main.ts, дали името използва същите главни и малки букви и дали файлът наистина експортира символа, който се опитваш да импортираш. Linux различава Arranque.ts от arranque.ts; проект, който е изглеждал, че работи в друга система, може да се счупи при пристигането си в Mint заради тази разлика.

Накрая разграничи грешка при компилация от грешка в командите. Ако напишеш tsc и терминалът отговори command not found, това не е диагностика на TypeScript: шелът не е намерил глобален изпълним файл. Вътре в проекта използвай npx tsc --version или npm run compilar. Така извикваш локалната версия, декларирана в package.json, без да зависиш от глобална инсталация.

Какво се прави погрешно

  • Да инсталираш TypeScript глобално и да приемеш, че всички ще използват същата версия. npm install --global typescript може да върши работа за експерименти, но не определя компилатора на revisor. Локалната зависимост и заключващият файл правят проекта възпроизводим. Използвай npx tsc или скриптове на npm, за да го изграждаш.

  • Да вярваш, че изпълнението на node src/main.ts е равностойно на проверка. Node 24 може да изтрие типовете и да изпълни .ts с изтриваем синтаксис, но не пуска tsc и не намира импортите .js, които проектът резервира за dist/. Използвай този режим само за изолиран скрипт; в revisor компилирай в dist/ и изпълнявай node dist/main.js.

  • Да смесваш генерирани файлове с изходни файлове. Ако оставиш .js, .map и .ts заедно, може да редактираш генериран изход или да изпълняваш стара версия. src/ е източникът; dist/ е резултатът. Изтрий и генерирай наново dist/, ако подозираш, че е остарял, а не го редактирай на ръка.

  • Да изключваш strict, за да „напредваш“. Отпусната конфигурация не премахва несигурността: само позволява да стигне по-далеч. Цената се плаща после, когато една функция приеме двусмислена стойност и грешката се появи далеч от причината си. Поправи диагностиката или разбери коя стойност може да липсва; не скривай предупреждението.

  • Да пишеш относителни ESM импорти без .js. TypeScript може да намери източника, но Node трябва да разреши издадения JavaScript. С NodeNext разширението .js е част от договора за изпълнение. Пиши го от самото начало и няма да се налага да поправяш всички импорти, когато проектът порасне.

  • Да използваш точка на прекъсване като доказателство, че кодът работи. Дебъгерът показва едно изпълнение, с конкретни данни. Тестът трябва да изразява какъв резултат очакваш за няколко случая и да може да се повтаря. Използвай дебъгера, за да откриеш какво се случва, а тестовете, които ще дойдат в урок 7, за да не се загуби поправката.

Упражнения

Упражнение 1 — Твоята измерена среда

Инсталирай Node 24 LTS и създай папката ~/proyectos/revisor. Инициализирай npm, инсталирай typescript@7.0.2 и @types/node@24 като зависимости за разработка. Провери node --version, npm --version и npx tsc --version. Запази package-lock.json и добави node_modules/ в .gitignore.

Упражнение 2 — Първото стартиране на revisor

Създай tsconfig.json със строгата конфигурация от този урок, включително опцията "types": ["node"]. Копирай програмата от фигура 01.02 в src/main.ts, нагласи текста така, че да отпечатва revisor: entorno listo, компилирай с npm run compilar и я изпълни с npm run arrancar. Потвърди, че изходът е в dist/, а не до изходния файл.

Упражнение 3 — Модул и диагностика

Отдели съобщението за стартиране в src/arranque.ts и направи src/main.ts да го импортира с разширението .js. Компилирай и го изпълни. После премахни временно разширението от импорта, изпълни npm run compilar, копирай кода TSxxxx, който се появява, и поправи импорта. Накрая постави точка на прекъсване вътре в експортираната функция и провери, че дебъгерът спира във файла .ts.

Решения

Решение 1

От корена на проекта трите проверки трябва да идентифицират Node 24, версия на npm и TypeScript 7.0.2. Точната второстепенна версия на Node може да се промени в рамките на линия 24, когато обновиш LTS; важното е да не изпълняваш Node 22, 23 или друга различна линия.

node --version
npm --version
npx tsc --version

Файлът .gitignore трябва да включва, като минимум, този ред:

node_modules/

Не включвай package-lock.json в .gitignore. Той е част от възпроизводимата дефиниция на проекта.

Решение 2

Очакваната структура е тази:

revisor/
  package.json
  package-lock.json
  tsconfig.json
  src/
    main.ts
  dist/
    main.js
    main.js.map

Блокът compilerOptions на tsconfig.json трябва да включва "types": ["node"], за да зарежда проектът декларациите на @types/node. След npm run compilar, npm run arrancar трябва да изпълни dist/main.js, а не src/main.ts. Ако dist/ не се появи, провери дали си изпълнил npm run compilar или npx tsc без да посочваш файлове. Ако посочиш файл в папка с tsconfig.json, TypeScript 7 показва TS5112; за да го изолираш, използвай --ignoreConfig и опциите, които ти трябват.

Решение 3

Правилният импорт в src/main.ts носи .js, макар файлът, който си написал, да се казва arranque.ts:

import { mensajeDeArranque } from "./arranque.js";

Очакваната диагностика при пропускане на разширението е TS2835. Когато го възстановиш, npm run compilar трябва да завърши без съобщения за грешка. Ако дебъгерът спре в dist/arranque.js вместо в src/arranque.ts, потвърди, че sourceMap още е true, компилирай наново и стартирай отново сесията за дебъгване.

Как разбирам, че съм успял

  • node --version започва с v24 и npx tsc --version отпечатва Version 7.0.2.
  • package.json декларира "type": "module" и TypeScript е в devDependencies.
  • tsconfig.json декларира "types": ["node"] и npm run verificar завършва без диагностики.
  • npm run compilar създава dist/main.js.
  • Следващата команда отпечатва точно посочения ред:
$ node dist/main.js
revisor: entorno listo
  • Относителен импорт на проекта използва .js и npm run compilar не съобщава TS2835.
  • Когато смениш число с текст в променлива, декларирана като number, компилаторът показва TS2322.
  • Точка на прекъсване в src/arranque.ts спира в TypeScript кода при изпълнение на изхода на Node.

За допълнително четене

  • TypeScript: какво е tsconfig.json — официална документация за корена на проекта, включените файлове и начина, по който компилаторът извиква конфигурацията. Консултирано на 2 октомври 2026 г.

  • TypeScript: справочник за опциите на TSConfig — официален справочник за strict, sourceMap, module, moduleResolution и останалите опции на компилатора. Консултирано на 2 октомври 2026 г.

  • Node.js: изтегляне и инсталиране — официална страница за избор на LTS линията и метода на инсталиране за Linux. Консултирано на 2 октомври 2026 г.

  • Visual Studio Code: транспилиране на TypeScript — официална документация на редактора за компилация, конфигурация и работа с TypeScript. Консултирано на 2 октомври 2026 г.

Да обсъдим вашия проект

Предпочитате имейл? Пишете ни на hola@habil.mx