Как настроить TypeScript с Node.js и Express

Создать сервер с JavaScript с использованием Node.js и Express довольно просто. Однако по мере того, как ваше приложение становится сложнее или при сотрудничестве с распределенной командой разработчиков со всего мира, TypeScript становится отличной альтернативой JavaScript.

TypeScript повышает надежность и ясность кода за счет статической типизации, что упрощает совместную работу и помогает масштабировать проект. Передовые инструменты, комплексная поддержка IDE и совместимость делают его отличным выбором для более удобной разработки, особенно в развивающихся проектах.

В этой статье мы рассмотрим удобный для новичков способ настройки TypeScript в приложении Express, чтобы понять фундаментальные ограничения, которые его сопровождают.

Создать package.json файл

Начните с создания нового каталога в локальной среде разработки и внутри него используйте команду инициализатора npm для создания файла package.json. Если вы используете менеджер пакетов, отличный от npm, рассмотрите возможность выполнения команды, init предоставляемой этим конкретным менеджером пакетов:

mkdir ts-node-express
cd ts-node-express/
npm init -y

При инициализации файла package.json таким способом флаг --yes или -y использует настройки по умолчанию, настроенные npm, минуя повторяющиеся вопросы с запросом подробностей проекта. Полученный файл package.json может выглядеть примерно так, как показано на следующем изображении:

Файл Package.JSON по умолчанию

Поскольку точкой входа в наше приложение будет src/index.js, о которой мы поговорим в следующих разделах, вам следует обновить поле main в файле package.json с index.js на src/index.js:

{
  "name": "ts-node-express",
  "version": "1.0.0",
  "description": "",
  "main": "src/index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  ...
}

Создайте минимальный сервер с помощью Express

После инициализации файла package.json добавьте в проект пакеты Expres и DotEnv. В окне терминала выполните следующую команду npm i:

npm i express dotenv

Пакет DotEnv используется для чтения переменных среды из файла .env. Вместо жесткого кодирования переменных, специфичных для среды, непосредственно в приложении, включите их все в этот файл и используйте пакет DotEnv для управления ими.

Например, чтобы указать номер порта вашего сервера, создайте файл .env с именем в корне каталога проекта. Внутри этого файла определите переменную среды PORT и установите для нее значение 3000. При необходимости в будущем рассмотрите возможность добавления в этот файл дополнительных переменных, специфичных для среды:

# Add all of the environmental variables here instead of 
# embedding them directly in the app and utilize them 
# with the `DotEnv` package.

PORT=3000

Затем создайте каталог src в корне проекта, чтобы организовать исходные файлы нашего приложения. Добавьте к нему новый файл index.js и заполните его следующим кодом, включающим ранее определенную переменную среды:

// src/index.js
const express = require('express');
const dotenv = require('dotenv');

dotenv.config();

const app = express();
const port = process.env.PORT;

app.get('/', (req, res) => {
  res.send('Express + TypeScript Server');
});

app.listen(port, () => {
  console.log(`[server]: Server is running at http://localhost:${port}`);
});

Приведенный выше код охватывает основные шаги по настройке минимального сервера Express с использованием простого JavaScript.

Для запуска сервера выполните команду node src/index.js в терминале. Это приведет к выполнению кода, который мы только что добавили index.js, и должен запустить новый сервер, как показано ниже:

Настройка экспресс-сервера

Сервер Express теперь запущен и работает, предлагая базовую настройку для разработки с помощью Express на Node.js. Далее давайте улучшим его, включив TypeScript в следующем разделе.

Установка TypeScript

Мы начнем с установки TypeScript в качестве зависимости для разработки. Кроме того, мы установим @types пакеты объявлений для Express и Node.js, которые предлагают определения типов в виде файлов объявлений.

Файлы объявлений, обычно с расширением .d.ts, служат предопределенными модулями, описывающими структуру значений JavaScript или типов, представленных для компилятора TypeScript. Эти файлы объявлений доступны для библиотек, изначально написанных на JavaScript, а не на TypeScript.

Репозиторий DefinitelyTyped GitHub поддерживает определения типов TypeScript для прямого использования в Node.js и других проектах JavaScript, избавляя вас от необходимости определять эти типы с нуля. Чтобы включить типы или файлы объявлений для конкретной библиотеки или модуля, найдите пакеты, начинающиеся с @types пространства имен.

Запустите терминал и установите описанные выше пакеты с помощью следующей команды:

npm i -D typescript @types/express @types/node

Флаг -D или --dev указывает менеджеру пакетов установить эти библиотеки в качестве зависимостей разработки.

Установка этих пакетов добавит devDependencies в файл package.json новый объект, содержащий сведения о версии для каждого пакета, как показано ниже:

{
  ...
  "devDependencies": {
    "@types/express": "^4.17.21",
    "@types/node": "^20.10.3",
    "typescript": "^5.3.2"
  },
  ...
}

Создание tsconfig.json

Каждый проект TypeScript использует файл tsconfig.json конфигурации для управления различными настройками проекта. Файл , который служит файлом конфигурации TypeScript, описывает эти параметры по умолчанию и предлагает гибкость для изменения или настройки параметров компилятора в соответствии с вашими потребностями.

Файл обычно размещается в корне проекта. Чтобы сгенерировать файл tsconfig.json, используйте следующую команду tsc, запускающую компилятор TypeScript:

npx tsc --init

Выполнив эту команду, вы заметите, что файл tsconfig.json создается в корне каталога вашего проекта. Этот файл содержит параметры компилятора по умолчанию, как показано на изображении ниже:

Файл Tsconfig.JSON

Открыв файл tsconfig.json, вы заметите несколько других закомментированных параметров компилятора.

Среди всех этих опций compilerOptions есть обязательное поле, которое необходимо указать. Вот сводка всех параметров по умолчанию, которые относятся к этому полю:

  • target: включает указание целевой версии JavaScript, которую выведет компилятор.
  • module: Облегчает использование менеджера модулей в скомпилированном коде JavaScript. Поддерживается CommonJS, который является стандартом Node.js.
  • strict: включает строгие протоколы проверки типов.
  • esModuleInterop: Включает компиляцию модулей ES6 в модули CommonJS.
  • skipLibCheck: если установлено значение true, проверка типов файлов объявлений библиотеки по умолчанию обходит проверку.
  • forceConsistentCasingInFileNames: если установлено значение true, в именах файлов учитывается регистр.

Одна из важнейших опций, которую вам нужно будет включить, — это outDir, которая определяет каталог назначения для скомпилированных результатов. Найдите эту опцию в файле tsconfig.json и раскомментируйте ее.

По умолчанию значение этой опции установлено в корень проекта. Измените его на dist, как показано ниже:

{
  "compilerOptions": {
    ...
    "outDir": "./dist"
    ...
  }
}

Хотя, вероятно, есть и другие параметры конфигурации, которые вы можете добавить в компилятор TypeScript, приведенные выше параметры являются базовыми спецификациями, которые могут помочь вам начать работу.

Теперь вам следует обновить main поле в файле, поскольку код TypeScript будет компилироваться из каталога package.json в dist/index.jssrcdist.

Создайте Express сервер с расширением .ts

Преобразование нашего серверного кода JavaScript Express в TypeScript не так сложно, как может показаться. Начните с переименования файла index.js из каталога src в index.ts. Расширение .ts указывает на файл TypeScript, и он будет скомпилирован в JavaScript, когда мы позже создадим приложение.

Теперь откройте файл index.ts и добавьте следующие изменения, чтобы сделать его совместимым с TypeScript:

// src/index.js
import express, { Express, Request, Response } from "express";
import dotenv from "dotenv";

dotenv.config();

const app: Express = express();
const port = process.env.PORT || 3000;

app.get("/", (req: Request, res: Response) => {
  res.send("Express + TypeScript Server");
});

app.listen(port, () => {
  console.log(`[server]: Server is running at http://localhost:${port}`);
});

В код не вносится никаких дополнительных изменений, за исключением включения некоторых типов TypeScript.

Теперь, если вы попытаетесь выполнить файл index.ts с помощью Node, аналогично тому, что мы сделали с нашим файлом index.js, вы столкнетесь с ошибкой:

Обнаружение ошибки при выполнении файла TypeScript с помощью Node

Это связано с тем, что Node по своей сути не поддерживает прямое выполнение файлов TypeScript. В следующем разделе обсуждается запуск файлов TypeScript в терминале с использованием пакета Node.

Запуск TypeScript в Node с помощью ts-node

Как обсуждалось ранее, выполнение файла TypeScript в Node по умолчанию не поддерживается. Однако мы можем преодолеть это ограничение, используя ts-node , среду выполнения TypeScript для Node. Давайте сначала воспользуемся ts-node с npx, не устанавливая его как зависимость, и посмотрим результат:

npx ts-node src/index.ts

Как показано ниже, наш файл index.ts успешно выполнился, и сервер начал работать как положено:

Файл TypeScript успешно выполнен

Основное преимущество использования ts-node заключается в том, что он исключает дополнительный этап транспиляции кода и позволяет работать с кодом TypeScript непосредственно в среде Node.js. Это также полезно при работе с автономными файлами TypeScript в терминале Node.

Наблюдение за изменениями файлов

Чтобы улучшить рабочий процесс разработки проектов Node.js, мы часто используюем nodemon — служебную библиотеку, которая автоматически перезапускает приложение на основе Node при обнаружении изменений файлов в указанных каталогах.

Еще один полезный пакет, который вы можете рассмотреть, — concurrently , который облегчает выполнение нескольких команд, таких как nodemon, npx, tsc и т. д., позволяя комбинировать различные функции. Однако для этой простой демонстрации приложения мы не будем включать его на данном этапе.

Мы также установим ts-node в качестве зависимости от разработки для дальнейшего улучшения рабочего процесса. Таким образом, nodemon автоматически выбирает ts-node, чтобы упростить процесс разработки. Выполните следующую команду, чтобы интегрировать nodemon и ts-node в качестве зависимостей разработки:

npm i -D nodemon ts-node

После установки этих зависимостей для разработчиков обновите scripts в файле package.json следующим образом:

{
  "scripts": {
    "build": "npx tsc",
    "start": "node dist/index.js",
    "dev": "nodemon src/index.ts"
  }
}

Ссылаясь на добавленные выше модификации сценария, build команда компилирует код в JavaScript и сохраняет его в dist каталоге с помощью компилятора TypeScript (tsc). Команда dev предназначена для запуска Express-сервера в режиме разработки с помощью nodemon и ts-node.

Наконец, вернитесь в окно терминала и выполните команду npm run dev, чтобы запустить сервер разработки. Должно быть показано что-то вроде этого:

Экспресс-сервер успешно работает с Nodemon

Ошибок нет, что подтверждает успешную работу сервера. Поскольку nodemon обнаружил изменения, давайте попробуем отредактировать отправленное сообщение, одновременно отслеживая терминал res.send() на предмет любых обнаруженных изменений nodemon:

Мониторинг изменений терминала узла, обнаруженных Nodemon

Сделав дополнительный шаг для более точной настройки, вы можете рассмотреть файл в корне проекта, который служит файлом конфигурации для nodemon. Этот файл nodemon.json позволяет вам указывать каталоги и расширения для просмотра и определять команды для выполнения, а nodemon управляет перезагрузкой приложения при изменениях:

{
  "watch": ["src"],
  "ext": "ts",
  "exec": "concurrently \"npx tsc --watch\" \"ts-node src/index.ts\""
}

Очень важно отметить, что сочетание команды компилятора TypeScript в режиме просмотра с ts-node или любой другой командой, как показано выше в конфигурации nodemon, или с самой командой bodemon, может привести к потере информации журнала.

Это связано с тем, что и nodemon, и TSC одновременно отслеживают изменения и потенциально конкурируют за отображение своих соответствующих журналов на экране.

Building или транспиляция файлов TypeScript

В проекте TypeScript транспиляция или сборка включает в себя компилятор TypeScript (TSC), который интерпретирует файл tsconfig.json, чтобы определить, как преобразовать файлы TypeScript в действительный JavaScript.

Для компиляции кода необходимо выполнить команду npm run build. При первом успешном выполнении этой команды distв корне проекта создается новый каталог.

В этом каталоге вы найдете скомпилированные версии наших файлов TypeScript в форме допустимого JavaScript. Этот скомпилированный JavaScript по сути используется в производственной среде:

'use strict';
var __importDefault =
  (this && this.__importDefault) ||
  function (mod) {
    return mod && mod.__esModule ? mod : { default: mod };
  };
Object.defineProperty(exports, '__esModule', { value: true });
const express_1 = __importDefault(require('express'));
const dotenv_1 = __importDefault(require('dotenv'));
dotenv_1.default.config();
const app = (0, express_1.default)();
const port = process.env.PORT;
app.get('/', (req, res) => {
  res.send('Express + TypeScript Server is running.');
});
app.listen(port, () => {
  console.log(`⚡️[server]: Server is running at http://localhost:${port}`);
});

Если вы укажете какой-либо другой каталог в качестве значения поля outDir в файле tsconfig.json, этот указанный каталог будет отражен здесь вместо dist.

Чтобы еще больше улучшить этот процесс, настройте TypeScript для обеспечения надежности со строгой проверкой типов и конфигурациями, которые адаптируются к вашим потребностям.

Получите максимальную отдачу от файла tsconfig.json, указав наиболее подходящие производственные настройки для вашего проекта. Повышайте производительность за счет разделения кода, используя такие инструменты, как Webpack, для повышения эффективности и сокращайте размеры файлов с помощью таких инструментов, как Terser.

Заключение

Использование TypeScript имеет свои преимущества, но требует некоторого обучения. Вам необходимо тщательно проанализировать, выгодно ли использование TypeScript в ваших бэкэнд-проектах Node.js и Express, что может зависеть от требований вашего проекта.