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 одним инструментом
ℹ Версия и статус
Effect 4.0 — первый стабильный релиз ветки v4. Effect 4.x является LTS-релизом с минимум тремя годами поддержки патчей безопасности и исправлений ошибок.

Ключевые возможности

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.

Ядро пакета теперь имеет нулевые внешние зависимости.

💡 LSP-плагин
Effect поставляется с Language Service Plugin (@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 требует понимания концепций функционального программирования и представляет значительный сдвиг парадигмы по сравнению с привычным TypeScript-кодом. Новичкам рекомендуется начать с официальной документации на effect.website.

Сравнение с альтернативами

Effect-TS — самый мощный вариант: полноценный async-рантайм, типизированные ошибки, DI и структурированная конкурентность. fp-ts — проверенный временем функциональный инструментарий, который сейчас вытесняется Effect в большинстве новых проектов.

ПараметрEffect-TS v4fp-tsneverthrow
Типизированные ошибки✅ Полная поддержка✅ Either<E,A>✅ Result<T,E>
DI / Layer✅ Встроено❌ Нет❌ Нет
Конкурентность✅ Fiber-based❌ Нет❌ Нет
Stream✅ Встроен✅ Частично (Task)❌ Нет
Schema/Валидация✅ Встроена❌ Нет❌ Нет
Кривая обучения🔴 Высокая🔴 Высокая🟢 Низкая
Размер🟡 ~20 КБ (v4)🟡 Средний🟢 Минимальный
Активность🟢 Активна🟡 Замедляется🔴 Слабая
Звёзд на GitHub~16.6K~11.5K~7.7K
ЛицензияMITMITMIT

fp-ts сливается в экосистему Effect — Effect является официальным преемником. Джулио Канти, создатель fp-ts, официально присоединился к команде Effect.

Более комплексные экосистемы, такие как Effect, уже появились, и если вам нужны только Result-типы, другие библиотеки могут казаться лишними.

📝 Когда выбрать neverthrow
Если вам нужна только типизированная обработка ошибок для небольшого проекта и вы не хотите изучать новую парадигму — 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
Открытость / MIT10/10
Итого8.5/10