Чат-боты на TypeScript: полный гайд по созданию с нуля

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Почему TypeScript — лучший выбор для чат-ботов?

Когда речь заходит о создании чат-ботов, многие разработчики сразу думают о Python или JavaScript. Но есть один язык, который сочетает в себе гибкость динамической типизации и безопасность статической проверки — это TypeScript. В этом практическом руководстве мы разберём, как создавать чат-ботов на TypeScript, которые будут не только работать стабильно, но и легко поддерживаться.

TypeScript — это не просто «надстройка» над JavaScript. Это полноценный инструмент, который позволяет писать код, который сложнее сломать. Представьте: вы пишете бота для Телеграма, и вдруг ваш коллега передаёт в функцию не строку, а число. В JavaScript вы узнаете об этом в рантайме, когда бот упадёт. В TypeScript компилятор скажет вам об ошибке ещё до запуска. Это ли не магия?

С чего начать: настройка окружения

Прежде чем мы погрузимся в код, давайте настроим рабочее место. Нам понадобится Node.js (версия 16 или выше) и пакетный менеджер npm или yarn.

Шаг 1: Инициализация проекта

mkdir my-chat-bot
cd my-chat-bot
npm init -y

Шаг 2: Установка зависимостей

Для работы с чат-ботами мы будем использовать популярную библиотеку telegraf (для Telegram) и discord.js (для Discord). Но в этом руководстве сфокусируемся на универсальном подходе.

npm install typescript @types/node telegraf dotenv
npx tsc --init

Файл tsconfig.json нужно немного подправить: включите strict: true и укажите outDir: "./dist". Это сделает код безопаснее.

Структура проекта для чат-ботов на TypeScript

Хорошая архитектура — залог успеха. Вот как я рекомендую организовать файлы:

src/
├── bot/
│   ├── index.ts          # Точка входа
│   ├── handlers/         # Обработчики команд
│   ├── middleware/        # Промежуточные обработчики
│   └── types/            # Типы и интерфейсы
├── config/
│   └── index.ts          # Конфигурация
└── utils/
    └── logger.ts         # Логирование

Пишем первого чат-бота на TypeScript

Давайте создадим простого Telegram-бота, который отвечает на команду /start и эхо-сообщения.

Файл: src/config/index.ts

import dotenv from 'dotenv';
dotenv.config();

export const config = {
  BOT_TOKEN: process.env.BOT_TOKEN || '',
  PORT: parseInt(process.env.PORT || '3000')
};

Файл: src/bot/index.ts

import { Telegraf } from 'telegraf';
import { config } from '../config';
import { startHandler } from './handlers/start';
import { echoHandler } from './handlers/echo';

const bot = new Telegraf(config.BOT_TOKEN);

// Регистрируем обработчики
bot.start(startHandler);
bot.on('text', echoHandler);

// Запускаем бота
bot.launch()
  .then(() => console.log('Бот запущен!'))
  .catch((err) => console.error('Ошибка запуска:', err));

// Graceful shutdown
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));

Файл: src/bot/handlers/start.ts

import { Context } from 'telegraf';

export const startHandler = async (ctx: Context) => {
  const userName = ctx.from?.first_name || 'друг';
  await ctx.reply(`Привет, ${userName}! Я бот на TypeScript. Напиши мне что-нибудь.`);
};

Файл: src/bot/handlers/echo.ts

import { Context } from 'telegraf';

export const echoHandler = async (ctx: Context) => {
  const message = ctx.message?.text || '';
  await ctx.reply(`Вы написали: "${message}". Круто!`);
};

Обратите внимание на типизацию: Context из библиотеки telegraf полностью типизирован. Это значит, что IDE подскажет вам все доступные методы и свойства. Чат-боты на TypeScript становятся предсказуемыми и удобными для отладки.

Продвинутые возможности: middleware и типы

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

Файл: src/bot/middleware/logger.ts

import { Context, Middleware } from 'telegraf';

export const loggerMiddleware: Middleware<Context> = async (ctx, next) => {
  const start = Date.now();
  const username = ctx.from?.username || 'unknown';
  console.log(`[${new Date().toISOString()}] @${username}: "${ctx.message?.text}"`);
  
  await next(); // Передаём управление следующему обработчику
  
  const ms = Date.now() - start;
  console.log(`Ответ отправлен за ${ms}ms`);
};

Теперь подключим этот middleware в главном файле:

// В bot/index.ts
import { loggerMiddleware } from './middleware/logger';

bot.use(loggerMiddleware);
// ... остальной код

Работа с внешними API: пример с погодой

Настоящий чат-бот должен быть полезным. Давайте сделаем команду /weather, которая показывает погоду в любом городе. Для этого нам понадобится API OpenWeatherMap.

Файл: src/bot/handlers/weather.ts

import { Context } from 'telegraf';
import { config } from '../../config';

interface WeatherResponse {
  main: { temp: number; feels_like: number };
  weather: Array<{ description: string }>;
  name: string;
}

export const weatherHandler = async (ctx: Context) => {
  const city = ctx.message?.text?.replace('/weather', '').trim();
  
  if (!city) {
    await ctx.reply('Укажите город: /weather Москва');
    return;
  }

  try {
    const response = await fetch(
      `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${config.WEATHER_API_KEY}&units=metric&lang=ru`
    );
    
    if (!response.ok) {
      await ctx.reply('Город не найден. Попробуйте другой.');
      return;
    }

    const data: WeatherResponse = await response.json();
    const message = `🌤 Погода в ${data.name}:
Температура: ${data.main.temp}°C (ощущается как ${data.main.feels_like}°C)
Описание: ${data.weather[0].description}`;
    
    await ctx.reply(message);
  } catch (error) {
    console.error('Ошибка при запросе погоды:', error);
    await ctx.reply('Произошла ошибка. Попробуйте позже.');
  }
};

Обратите внимание на интерфейс WeatherResponse — это ещё одно преимущество TypeScript. Вы точно знаете, какие данные придут от API, и можете безопасно к ним обращаться.

Развёртывание бота: от разработки до продакшена

Блоги

Рекомендаций по книгам