blog.dopana

Back

Effect (effect.website) là một thư viện TypeScript mạnh mẽ, mang typed effects, error handling có cấu trúc, quản lý dependency và concurrency vào hệ sinh thái TypeScript. Không giống như các thư viện functional programming khác, Effect được thiết kế để thay thế hoàn toàn try/catch, Promise, và dependency injection truyền thống bằng một hệ thống thống nhất, type-safe.

Vấn đề với TypeScript thuần#

TypeScript không có cơ chế native để:

Vấn đềCách xử lý hiện tạiHạn chế
Lỗi có kiểuthrow new Error()Không biết kiểu lỗi ở call site
Dependency injectionConstructor injection, DI containerKhông type-safe, runtime overhead
Tác vụ bất đồng bộPromise, async/awaitKhông cancel được, không compose
Tác vụ song songPromise.all()Lỗi một → hỏng tất cả
Resource managementtry/finallyDễ quên cleanup

Effect giải quyết tất cả những vấn đề này trong một framework duy nhất.

Core Concepts#

1. Effect — Đơn vị cơ bản#

Effect là một mô tả type-safe của một tác vụ có thể thất bại. Bạn không chạy code ngay lập tức — bạn xây dựng một pipeline, sau đó run nó:

import { Effect } from 'effect'

// Một effect thành công (never fails)
const success: Effect.Effect<number, never, never> = Effect.succeed(42)

// Một effect có thể thất bại
const fail: Effect.Effect<number, string, never> = Effect.fail('Something went wrong')

// Run effect
const result = await Effect.runPromise(success)
console.log(result) // 42
ts

Chữ ký type Effect<Success, Error, Requirements> cho bạn biết:

  • Success: kiểu trả về khi thành công
  • Error: kiểu lỗi có thể xảy ra
  • Requirements: dependencies cần thiết

2. Error Handling có kiểu#

Không còn catch (e: unknown) nữa:

3. Dependency Injection type-safe#

Effect quản lý dependencies thông qua LayerContext — không runtime, không global state:

4. Concurrency & Fibers#

Effect có hệ thống Fiber riêng — lightweight threads có thể cancel, fork, và join:

import { Effect, Fiber } from 'effect'

// Fork — chạy song song
const task1 = Effect.succeed('Task 1').pipe(Effect.delay('1 second'))
const task2 = Effect.succeed('Task 2').pipe(Effect.delay('2 seconds'))

// Race — lấy kết quả nhanh nhất
const winner = Effect.raceAll([task1, task2])

// Fork/Join — chạy song song, đợi tất cả
const fiber = yield* Effect.fork(task1)
const result = yield* Fiber.join(fiber)

// Timeout — tự động fail nếu quá lâu
const withTimeout = task1.pipe(Effect.timeout('500 millis'))
ts

5. Scoped Resources#

Quản lý resource tự động — không lo quên close():

6. Streams#

Stream là phiên bản có kiểu của Observable/AsyncIterable:

import { Stream, Sink, Effect } from 'effect'

const numbers = Stream.iterate(0, (n) => n + 1).pipe(
  Stream.take(5),
  Stream.map((n) => n * 2)
)

// Collect thành array
const result = await Effect.runPromise(
  Stream.runCollect(numbers)
)
// [0, 2, 4, 6, 8]
ts

Ecosystem#

Effect có một hệ sinh thái đang phát triển nhanh:

PackageMục đích
effect/SchemaSchema validation & marshalling (thay thế Zod)
effect/PlatformFile system, path, streams platform APIs
@effect/sqlSQL database access (Postgres, SQLite, MySQL)
@effect/rpcRPC framework với type-safe protocols
@effect/clusterDistributed computing cluster
@effect/opentelemetryOpenTelemetry observability
effect/CronCron job scheduling

Effect vs các giải pháp khác#

Tiêu chítry/catchPromiseZodfp-tsEffect
Error type-safe
Dependency injection
Cancellation
Resource safety
Concurrency
Streaming
Schema validation

Effect trong thực tế#

Alchemy — Infrastructure as Code#

Alchemy (alchemy.run) sử dụng Effect làm nền tảng để định nghĩa và quản lý cloud infrastructure. Effect cho phép xử lý lỗi mạng, retry, và resource lifecycle một cách an toàn:

import { Effect } from 'effect'

// Effect xử lý retry khi API call thất bại
const provision = Effect.retry(
  cloudflare.createBucket('my-bucket'),
  { times: 3, delay: '1 second' }
)
ts

Web Framework — effect-http#

Bắt đầu với Effect#

# Tạo project
mkdir my-effect-app && cd my-effect-app
npm init -y
npm install effect @effect/platform @effect/platform-bun
shell
main.ts
import { Effect, Console } from 'effect'

const program = Effect.gen(function* () {
  const name = yield* Effect.succeed('World')
  yield* Console.log(`Hello, ${name}!`)
  return name
})

Effect.runPromise(program).then(console.log)
ts

Kết luận#

Effect không chỉ là một thư viện — nó là một cách tiếp cận mới để viết TypeScript. Với hệ thống kiểu mạnh mẽ, error handling có cấu trúc, và quản lý dependency type-safe, Effect giúp bạn viết code đáng tin cậy hơn, dễ maintain hơn, và dễ test hơn.

Nếu bạn muốn đưa TypeScript lên một tầm cao mới, Effect là công cụ đáng đầu tư thời gian nhất hiện nay.

Link: effect.website
GitHub: github.com/Effect-TS/effect
Discord: discord.gg/effect-ts