Effect-TS: production-ready TypeScript без боли
Обзор Effect-TS v4 — мощной open-source библиотеки для TypeScript: typed errors, DI, конкурентность, Schema и многое другое.
Effect-TS: production-ready TypeScript без боли
Что это и для кого
Effect — библиотека для создания надёжных, поддерживаемых, типобезопасных и production-ready приложений на TypeScript. Она помогает справляться со сложными проблемами в масштабе: типизированные ошибки, dependency injection, структурированная конкурентность, планирование задач, трассировка и унифицированная валидация схем.
Долгое время TypeScript не имел полноценной стандартной библиотеки. В то время как Rust, Go или Python предлагают встроенные инструменты для обработки ошибок, конкурентности и побочных эффектов, разработчики TypeScript были вынуждены прибегать к множеству специализированных библиотек. Effect-TS меняет это, предлагая единое и мощное решение для современной разработки.
Проект вдохновлён ZIO из экосистемы Scala и привносит принципы функционального программирования в TypeScript практичным и доступным способом.
Для кого подойдёт:
- Backend-разработчики на Node.js / Bun / Deno
- Команды, строящие сложные микросервисы и распределённые системы
- Разработчики, которым надоело хаотичное
try/catch - Те, кто хочет заменить связку Zod + Lodash + RxJS одним инструментом
Ключевые возможности
1. Типобезопасная обработка ошибок
Effect-TS решает три проблемы, с которыми TypeScript борется нативно: типобезопасная обработка ошибок, async-операции и dependency injection — причём без необходимости разбираться в теории категорий.
Сравним классический подход и Effect-TS:
// ❌ Традиционный TypeScript — тип ошибки unknown
async function fetchUser(id: string): Promise<User> {
try {
const res = await fetch(`/api/users/${id}`);
if (!res.ok) throw new Error('Not found');
return res.json();
} catch (e) {
throw e; // Что внутри e? Неизвестно!
}
}
// ✅ Effect-TS — ошибки явно в типе
const fetchUser = (id: string): Effect.Effect<User, UserNotFoundError | NetworkError> =>
pipe(
Effect.tryPromise({
try: () => fetch(`/api/users/${id}`),
catch: (e) => new NetworkError({ cause: e }),
}),
Effect.flatMap(response =>
response.ok
? Effect.tryPromise({
try: () => response.json() as Promise<User>,
catch: () => new UserNotFoundError({ id }),
})
: Effect.fail(new UserNotFoundError({ id }))
)
);
Благодаря системе типов TypeScript Effect помогает обнаруживать труднодетектируемые проблемы ещё на этапе компиляции.
2. Структурированная конкурентность (Fiber-based)
Одна из ключевых особенностей Effect — использование структурированной конкурентности для предоставления таких возможностей, как отмена async-операций и безопасное управление ресурсами, что упрощает создание надёжных, масштабируемых и эффективных программ.
Fiber — это лёгкие виртуальные потоки с возможностью безопасной отмены, которые являются основой большинства возможностей Effect.
import { Effect, Fiber } from 'effect';
// Параллельный запуск двух задач
const program = Effect.gen(function* () {
const fiber1 = yield* Effect.fork(longRunningTask1());
const fiber2 = yield* Effect.fork(longRunningTask2());
const [result1, result2] = yield* Fiber.joinAll([fiber1, fiber2]);
return { result1, result2 };
});
3. Dependency Injection без фреймворков
Context — лёгкий механизм dependency injection, позволяющий передавать сервисы через вычисления без прямых ссылок. Layer — система управления зависимостями, обеспечивающая модульное и компонуемое выделение ресурсов.
import { Context, Layer, Effect } from 'effect';
// Определяем сервис
class Database extends Context.Tag('Database')<Database, { query: (sql: string) => Effect.Effect<Row[]> }>()
{}
// Реализация через Layer
const DatabaseLive = Layer.succeed(Database, {
query: (sql) => Effect.tryPromise(() => db.execute(sql))
});
// Используем без прямого импорта
const getUsers = Effect.gen(function* () {
const db = yield* Database;
return yield* db.query('SELECT * FROM users');
});
4. Schema — валидация данных
Schema — мощная библиотека для определения, валидации и трансформации структурированных данных с типобезопасным кодированием и декодированием. Schema v4 — это новая реализация с более быстрым парсингом, class-based схемами, конструкторами make на каждой схеме и effectful-декодированием через сервисы.
5. Stream, Schedule и другие модули
Stream — мощная абстракция для обработки асинхронных, событийно-ориентированных данных. Schedule — модуль для определения политик повторных попыток и расписаний с возможностью компоновки.
6. Новинки Effect v4
В v4 добавлены новые пакеты: @effect/platform-deno, @effect/sql-pglite, @effect/ai-openai-compat, @effect/ai-typesafe, @effect/atom-react, @effect/atom-solid, @effect/atom-vue, @effect/openapi-generator и @effect/doctest.
В v4 функциональность, ранее жившая в отдельных пакетах, теперь поставляется внутри effect под пространствами имён effect/*, включая http, http-api, rpc, cluster, workflow, cli, ai, sql и reactivity.
Ядро пакета теперь имеет нулевые внешние зависимости.
@effect/language-service), который добавляет диагностику прямо в IDE. LSP-диагностики Effect теперь доступны также на этапе компиляции благодаря ts-patch.Архитектура Effect-программы
graph TD
A[Описание эффекта
Effect<A, E, R>] --> B[Layer / Context
Dependency Injection]
B --> C[Runtime]
C --> D{Выполнение}
D --> E[Success: A]
D --> F[Failure: E]
D --> G[Defect / Panic]
A --> H[Schema
Валидация данных]
A --> I[Fiber
Конкурентность]
A --> J[Stream
Потоки данных]
A --> K[Schedule
Повторы / таймеры]
Тарифы и лицензия
Effect распространяется под лицензией MIT и является полностью бесплатным и открытым проектом. Коммерческого использования нет никаких ограничений. Монетизация проекта осуществляется через:
- Effect Cloud (в разработке) — хостинг для Workflows и Cluster
- Effect Days — ежегодная конференция
- Спонсорство на GitHub
Effect — полностью open-source инструмент. Ни один из базовых модулей не требует платной подписки.
Плюсы и минусы
| Критерий | Оценка |
|---|---|
| Типобезопасность | ✅ Исчерпывающая, ошибки видны в сигнатуре |
| Конкурентность | ✅ Fiber-based, отмена, backpressure |
| DI без фреймворков | ✅ Layer + Context из коробки |
| Экосистема | ✅ HTTP, SQL, AI, RPC, CLI в одном пакете |
| LTS-поддержка | ✅ v4 — минимум 3 года |
| Кривая обучения | ⚠️ Высокая для новичков |
| Размер бандла | ⚠️ v3 ~70 КБ (v4 сократил до ~20 КБ) |
| Парадигма | ⚠️ Требует перестройки мышления |
| CRUD-проекты | ❌ Избыточен для простых приложений |
Сравнение с альтернативами
Effect-TS — самый мощный вариант: полноценный async-рантайм, типизированные ошибки, DI и структурированная конкурентность. fp-ts — проверенный временем функциональный инструментарий, который сейчас вытесняется Effect в большинстве новых проектов.
| Параметр | Effect-TS v4 | fp-ts | neverthrow |
|---|---|---|---|
| Типизированные ошибки | ✅ Полная поддержка | ✅ Either<E,A> | ✅ Result<T,E> |
| DI / Layer | ✅ Встроено | ❌ Нет | ❌ Нет |
| Конкурентность | ✅ Fiber-based | ❌ Нет | ❌ Нет |
| Stream | ✅ Встроен | ✅ Частично (Task) | ❌ Нет |
| Schema/Валидация | ✅ Встроена | ❌ Нет | ❌ Нет |
| Кривая обучения | 🔴 Высокая | 🔴 Высокая | 🟢 Низкая |
| Размер | 🟡 ~20 КБ (v4) | 🟡 Средний | 🟢 Минимальный |
| Активность | 🟢 Активна | 🟡 Замедляется | 🔴 Слабая |
| Звёзд на GitHub | ~16.6K | ~11.5K | ~7.7K |
| Лицензия | MIT | MIT | MIT |
fp-ts сливается в экосистему Effect — Effect является официальным преемником. Джулио Канти, создатель fp-ts, официально присоединился к команде Effect.
Более комплексные экосистемы, такие как Effect, уже появились, и если вам нужны только Result-типы, другие библиотеки могут казаться лишними.
neverthrow остаётся отличным прагматичным выбором. Начните с Neverthrow, а потом переходите на Effect, когда сложность проекта это оправдает.Вердикт
Effect-TS упрощает типичные для веб-разработки задачи с помощью функционального подхода. Используя систему типов TypeScript, он позволяет поймать труднодетектируемые проблемы на этапе компиляции. Команды, ранее использовавшие fp-ts, обнаружили, что Effect-TS предоставляет абстракции, которые более точно соответствуют ежедневным задачам, а также делает код более лёгким для компоновки и тестирования.
Кому подойдёт:
- ✅ Командам, строящим сложные backend-сервисы на Node.js / Bun / Deno
- ✅ Проектам, где критична надёжность и observability
- ✅ Разработчикам, готовым вложить время в изучение новой парадигмы
- ✅ Тем, кто хочет заменить 5–6 библиотек одной
Кому НЕ подойдёт:
- ❌ Небольшим командам с простыми CRUD-приложениями
- ❌ Проектам с жёсткими требованиями к минимальному размеру бандла (хотя v4 значительно улучшил ситуацию)
- ❌ Разработчикам без времени на изучение функциональных концептов
Итоговая оценка: 8.5 / 10
| Критерий | Балл |
|---|---|
| Функциональность | 10/10 |
| Документация | 9/10 |
| Экосистема | 9/10 |
| Простота входа | 5/10 |
| Производительность | 9/10 |
| Открытость / MIT | 10/10 |
| Итого | 8.5/10 |