TypeScript Has No Standard Library
Python has os, json, datetime, collections, itertools. Go has net/http, encoding/json, fmt.
TypeScript has... npm. Want retries? Install a package. Want schema validation? Another package. Want proper error handling? Another package. Want concurrency control? Another package.
Effect: A Standard Library for TypeScript
Effect is a comprehensive TypeScript library that handles errors, concurrency, retries, streaming, dependency injection, and more — with full type safety.
Error Handling That Actually Works
In regular TypeScript, errors are invisible:
// What can go wrong? TypeScript has no idea.
async function getUser(id: string): Promise<User> {
const res = await fetch(`/api/users/${id}`) // NetworkError?
const data = await res.json() // ParseError?
return UserSchema.parse(data) // ValidationError?
}
With Effect, errors are part of the type:
import { Effect } from 'effect'
const getUser = (id: string): Effect.Effect<
User, // Success type
NetworkError | ParseError, // Error types (VISIBLE!)
HttpClient // Dependencies needed
> => ...
// TypeScript FORCES you to handle errors
const result = getUser('123').pipe(
Effect.catchTag('NetworkError', () => fallbackUser),
Effect.catchTag('ParseError', () => Effect.fail(new AppError()))
)
Built-in Retries
import { Effect, Schedule } from 'effect'
const fetchWithRetry = fetchData.pipe(
Effect.retry(
Schedule.exponential('1 second').pipe(
Schedule.compose(Schedule.recurs(3))
)
)
)
// Retries 3 times with exponential backoff. Type-safe. No library.
Concurrency Control
// Process 100 items, max 10 at a time
const results = Effect.forEach(
items,
(item) => processItem(item),
{ concurrency: 10 }
)
Dependency Injection
import { Context, Effect, Layer } from 'effect'
class Database extends Context.Tag('Database')<
Database,
{ query: (sql: string) => Effect.Effect<Row[]> }
>() {}
// Your code declares what it needs
const getUsers = Database.pipe(
Effect.flatMap(db => db.query('SELECT * FROM users'))
)
// Tests provide a mock
const testLayer = Layer.succeed(Database, {
query: () => Effect.succeed([{ id: 1, name: 'Test' }])
})
// Production provides the real thing
const prodLayer = Layer.succeed(Database, {
query: (sql) => pgPool.query(sql)
})
When to Use Effect
- Complex business logic with many failure modes
- Data pipelines with retries, timeouts, and concurrency
- Backend services that need structured error handling
- Teams that want fewer runtime surprises
When It Is Overkill
- Simple CRUD apps
- Frontend components
- Scripts and one-off tasks
- Teams new to functional programming concepts
Get Started
npm install effect
Building data pipelines? 88+ production scrapers on Apify handle retries, rate limits, and anti-bot for you. Custom solutions: spinov001@gmail.com
Top comments (0)