Skip to content

Почему GramIO

GramIO — это TypeScript-first фреймворк для Telegram Bot API, работающий на Node.js, Bun и Deno. Он построен вокруг одной идеи: система типов должна работать на вас, а не против вас.

Вот что это значит на практике.


Типы, которые текут, а не с которыми борешься

Большинство фреймворков дают вам типизированный контекст на входе. GramIO идёт дальше — типы распространяются по всей цепочке по мере её построения.

ts
import { 
Bot
} from "gramio";
import {
db
} from "./db";
const
bot
= new
Bot
(
process
.
env
.
BOT_TOKEN
as string)
// добавляем в каждый обработчик — типизируется автоматически .
derive
(async (
ctx
) => ({
user
: await
db
.
getUser
(
ctx
.from!.id),
Property 'from' does not exist on type 'Context<Bot<{}, DeriveDefinitions>>'.
})) // ctx.user полностью типизирован здесь .
on
("message", (
ctx
) => {
ctx
.
user
.
role
;
// // return
ctx
.
send
(`Привет, ${
ctx
.
user
.
name
}!`);
}) // ...и здесь, для другого события .
on
("callback_query", (
ctx
) =>
ctx
.
user
.
balance
);

Никакого приведения типов. Никаких ручных аннотаций. Никакого (ctx as any).user.


Форматирование без parse_mode

Форматирование Telegram через HTML или MarkdownV2 — это боль: нужно экранировать всё вручную и следить за parse_mode. GramIO использует тегированные шаблонные строки, которые создают корректные объекты MessageEntity:

ts
bot
.
command
("start", (
ctx
) =>
ctx
.
send
(
format
`${
bold
`Добро пожаловать!`} — ${
italic
("parse_mode не нужен")}.
Версия: ${
code
("2.0.0")}
${
spoiler
`секрет`} · ${
link
("gramio.dev", "https://gramio.dev")}`
) );

Никакого экранирования. Никакого parse_mode: "HTML". Никаких сломанных сообщений из-за < или > в тексте.


Плагины, которые компонуются, а не конфигурируются

Плагины в GramIO используют .extend() — тот же механизм, что и всё остальное. Плагин может добавлять свойства контекста, регистрировать обработчики и встраиваться в жизненный цикл. И всё это с полной типизацией:

ts
import { 
Bot
} from "gramio";
import {
scenes
,
Scene
} from "@gramio/scenes";
import {
session
} from "@gramio/session";
const
onboarding
= new
Scene
("onboarding")
.
step
("message", (
ctx
) => {
if (
ctx
.
scene
.
step
.
firstTime
) return
ctx
.
send
("Как вас зовут?");
return
ctx
.
scene
.
update
({
name
:
ctx
.
text
});
}) .
step
("message", (
ctx
) =>
ctx
.
send
(`Добро пожаловать, ${
ctx
.
scene
.
state
.
name
}!`)
); const
bot
= new
Bot
(
process
.
env
.
BOT_TOKEN
as string)
.
extend
(
session
())
.
extend
(
scenes
([
onboarding
]))
.
command
("start", (
ctx
) =>
c
tx
.
scene
.
enter
(
onboarding
))
;
// полная типизация — ctx.scene из плагина
bot
.
start
();

Сравнение

ВозможностьGramIOgrammYTelegraf
ЯзыкTypeScriptTypeScriptTypeScript
Распространение типов через middleware✅ Полное✅ Полное⚠️ Частичное
derive() с авто-типизацией контекста
Форматирование без parse_mode✅ Встроено❌ Вручную❌ Вручную
Система плагинов.extend()✅ Flavors⚠️ Middleware
Мультирантайм (Node/Bun/Deno)⚠️ Node в приоритете
Автогенерируемые типы API✅ Авто-публикация⚠️
Встроенные утилиты для тестирования@gramio/test
Полный референс Telegram API/telegram/
Сцены / диалоги@gramio/scenes✅ Conversations✅ Scenes
I18n@gramio/i18n (Fluent)⚠️
CLI для скаффолдингаcreate gramio

Всё — это Composer

Bot расширяет Composer — цепочный типобезопасный конвейер обработки middleware. Каждый .derive(), .guard(), .on() возвращает обновлённый тип. Можно выделить Composer для любой фичи, тестировать его изолированно, а затем .extend() его в бот:

ts
// src/plugins/index.ts — регистрация один раз
export const composer = new Composer()
    .extend(session())
    .extend(scenes([onboarding]));

// src/features/profile.ts — полная типизация, Bot не нужен
export const profileFeature = new Composer()
    .extend(composer)          // наследует ctx.session, ctx.scene
    .command("profile", (ctx) => ctx.send(ctx.session.name ?? "anon"));

// src/index.ts — склеиваем всё
const bot = new Bot(token)
    .extend(composer)
    .extend(profileFeature);

Готовы создавать?