Scala-like for-comprehensions
Compose monadic operations elegantly without nested flatMap calls
Do-notation provides generator-based monadic comprehensions inspired by Scala's for-comprehensions. It makes complex monadic chains readable and maintainable by eliminating nested flatMap calls.
// Chain multiple Option operations
const result = Do(function* () {
const x = yield* $(Option(5))
const y = yield* $(Option(10))
const z = yield* $(Option(2))
return x + y + z
}) // Some(17)
// Error handling with Either
const validation = Do(function* () {
const name = yield* $(Right<string, string>("John"))
const age = yield* $(Right<string, number>(25))
return { name, age }
})
// Async operations
// eslint-disable-next-line @typescript-eslint/require-await -- Generator function for demo purposes
const _asyncResult = DoAsync(async function* () {
const data = yield* $(Right("user123"))
const user = yield* $(Option({ id: data, name: "Alice" }))
return `User: ${user.name}`
})
Similar syntax to Scala's for-comprehensions with generators
Full TypeScript inference with the $ helper function
None/Left/Failure automatically propagates through the chain
175x faster than nested flatMaps for List comprehensions
const result = Do(function* () {
const x = yield* $(Option(5))
const y = yield* $(Option(10))
return x + y
}) // Option(15)
const pairs = Do(function* () {
const x = yield* $(List([1, 2]))
const y = yield* $(List([10, 20]))
return { x, y }
})
// List([{x:1,y:10}, {x:1,y:20}, {x:2,y:10}, {x:2,y:20}])
const validated = Do(function* () {
const email = yield* $(validateEmail(input))
const user = yield* $(fetchUser(email))
const saved = yield* $(saveUser(user))
return saved
})
// If any step returns Left, chain short-circuits
Complex workflows with multiple sequential steps
Generating combinations, test data, permutations
Business logic, validation pipelines, data transformations