<A, B>(f: (a: NoInfer<A>, i: number) => Iterable<B>): (
self: Iterable<A>
) => Iterable<B>
<A, B>(
self: Iterable<A>,
f: (a: NoInfer<A>, i: number) => Iterable<B>
): Iterable<B>Applies a function to each element in an Iterable and returns a new Iterable containing the concatenated mapped elements.
Example (Flat mapping iterables)
import { Iterable } from "effect"
// Expand each number to a range
const numbers = [1, 2, 3]
const expanded = Iterable.flatMap(numbers, (n) => Iterable.range(1, n))
console.log(Array.from(expanded)) // [1, 1, 2, 1, 2, 3]
// Split strings into characters
const words = ["hi", "bye"]
const chars = Iterable.flatMap(words, (word) => word)
console.log(Array.from(chars)) // ["h", "i", "b", "y", "e"]
// Conditional expansion with empty iterables
const values = [1, 2, 3, 4, 5]
const evenMultiples = Iterable.flatMap(
values,
(n) => n % 2 === 0 ? [n, n * 2, n * 3] : []
)
console.log(Array.from(evenMultiples)) // [2, 4, 6, 4, 8, 12]
// Use index in transformation
const letters = ["a", "b", "c"]
const indexed = Iterable.flatMap(
letters,
(letter, i) => Iterable.replicate(letter, i + 1)
)
console.log(Array.from(indexed)) // ["a", "b", "b", "c", "c", "c"]export const const flatMap: {
<A, B>(
f: (a: NoInfer<A>, i: number) => Iterable<B>
): (self: Iterable<A>) => Iterable<B>
<A, B>(
self: Iterable<A>,
f: (a: NoInfer<A>, i: number) => Iterable<B>
): Iterable<B>
}
Applies a function to each element in an Iterable and returns a new Iterable containing the concatenated mapped elements.
Example (Flat mapping iterables)
import { Iterable } from "effect"
// Expand each number to a range
const numbers = [1, 2, 3]
const expanded = Iterable.flatMap(numbers, (n) => Iterable.range(1, n))
console.log(Array.from(expanded)) // [1, 1, 2, 1, 2, 3]
// Split strings into characters
const words = ["hi", "bye"]
const chars = Iterable.flatMap(words, (word) => word)
console.log(Array.from(chars)) // ["h", "i", "b", "y", "e"]
// Conditional expansion with empty iterables
const values = [1, 2, 3, 4, 5]
const evenMultiples = Iterable.flatMap(
values,
(n) => n % 2 === 0 ? [n, n * 2, n * 3] : []
)
console.log(Array.from(evenMultiples)) // [2, 4, 6, 4, 8, 12]
// Use index in transformation
const letters = ["a", "b", "c"]
const indexed = Iterable.flatMap(
letters,
(letter, i) => Iterable.replicate(letter, i + 1)
)
console.log(Array.from(indexed)) // ["a", "b", "b", "c", "c", "c"]
flatMap: {
<function (type parameter) A in <A, B>(f: (a: NoInfer<A>, i: number) => Iterable<B>): (self: Iterable<A>) => Iterable<B>A, function (type parameter) B in <A, B>(f: (a: NoInfer<A>, i: number) => Iterable<B>): (self: Iterable<A>) => Iterable<B>B>(
f: (
a: NoInfer<A>,
i: number
) => Iterable<B>
f: (a: NoInfer<A>a: type NoInfer<A> = [A][A extends any ? 0 : never]Prevents TypeScript from inferring a type parameter from a specific
position.
When to use
Use when a function parameter must match an inferred type without becoming
an inference source.
Details
The parameter using NoInfer must still match the inferred type.
Example (Controlling inference)
import type { Types } from "effect"
declare function withDefault<T>(value: T, fallback: Types.NoInfer<T>): T
// T is inferred as "a" | "b" from the first argument only
const result = withDefault<"a" | "b">("a", "b")
NoInfer<function (type parameter) A in <A, B>(f: (a: NoInfer<A>, i: number) => Iterable<B>): (self: Iterable<A>) => Iterable<B>A>, i: numberi: number) => interface Iterable<T, TReturn = any, TNext = any>Iterable<function (type parameter) B in <A, B>(f: (a: NoInfer<A>, i: number) => Iterable<B>): (self: Iterable<A>) => Iterable<B>B>
): (self: Iterable<A>self: interface Iterable<T, TReturn = any, TNext = any>Iterable<function (type parameter) A in <A, B>(f: (a: NoInfer<A>, i: number) => Iterable<B>): (self: Iterable<A>) => Iterable<B>A>) => interface Iterable<T, TReturn = any, TNext = any>Iterable<function (type parameter) B in <A, B>(f: (a: NoInfer<A>, i: number) => Iterable<B>): (self: Iterable<A>) => Iterable<B>B>
<function (type parameter) A in <A, B>(self: Iterable<A>, f: (a: NoInfer<A>, i: number) => Iterable<B>): Iterable<B>A, function (type parameter) B in <A, B>(self: Iterable<A>, f: (a: NoInfer<A>, i: number) => Iterable<B>): Iterable<B>B>(self: Iterable<A>self: interface Iterable<T, TReturn = any, TNext = any>Iterable<function (type parameter) A in <A, B>(self: Iterable<A>, f: (a: NoInfer<A>, i: number) => Iterable<B>): Iterable<B>A>, f: (
a: NoInfer<A>,
i: number
) => Iterable<B>
f: (a: NoInfer<A>a: type NoInfer<A> = [A][A extends any ? 0 : never]Prevents TypeScript from inferring a type parameter from a specific
position.
When to use
Use when a function parameter must match an inferred type without becoming
an inference source.
Details
The parameter using NoInfer must still match the inferred type.
Example (Controlling inference)
import type { Types } from "effect"
declare function withDefault<T>(value: T, fallback: Types.NoInfer<T>): T
// T is inferred as "a" | "b" from the first argument only
const result = withDefault<"a" | "b">("a", "b")
NoInfer<function (type parameter) A in <A, B>(self: Iterable<A>, f: (a: NoInfer<A>, i: number) => Iterable<B>): Iterable<B>A>, i: numberi: number) => interface Iterable<T, TReturn = any, TNext = any>Iterable<function (type parameter) B in <A, B>(self: Iterable<A>, f: (a: NoInfer<A>, i: number) => Iterable<B>): Iterable<B>B>): interface Iterable<T, TReturn = any, TNext = any>Iterable<function (type parameter) B in <A, B>(self: Iterable<A>, f: (a: NoInfer<A>, i: number) => Iterable<B>): Iterable<B>B>
} = import dualdual(
2,
<function (type parameter) A in <A, B>(self: Iterable<A>, f: (a: A, i: number) => Iterable<B>): Iterable<B>A, function (type parameter) B in <A, B>(self: Iterable<A>, f: (a: A, i: number) => Iterable<B>): Iterable<B>B>(self: Iterable<A>self: interface Iterable<T, TReturn = any, TNext = any>Iterable<function (type parameter) A in <A, B>(self: Iterable<A>, f: (a: A, i: number) => Iterable<B>): Iterable<B>A>, f: (a: A, i: number) => Iterable<B>f: (a: Aa: function (type parameter) A in <A, B>(self: Iterable<A>, f: (a: A, i: number) => Iterable<B>): Iterable<B>A, i: numberi: number) => interface Iterable<T, TReturn = any, TNext = any>Iterable<function (type parameter) B in <A, B>(self: Iterable<A>, f: (a: A, i: number) => Iterable<B>): Iterable<B>B>): interface Iterable<T, TReturn = any, TNext = any>Iterable<function (type parameter) B in <A, B>(self: Iterable<A>, f: (a: A, i: number) => Iterable<B>): Iterable<B>B> => const flatten: <B>(
self: Iterable<Iterable<B>>
) => Iterable<B>
Flattens an Iterable of Iterables into a single Iterable
Example (Flattening nested iterables)
import { Iterable } from "effect"
// Flatten nested arrays
const nested = [[1, 2], [3, 4], [5, 6]]
const flat = Iterable.flatten(nested)
console.log(Array.from(flat)) // [1, 2, 3, 4, 5, 6]
// Flatten different iterable types
const mixed: Array<Iterable<string>> = ["ab", "cd"]
const flatMixed = Iterable.flatten(mixed)
console.log(Array.from(flatMixed)) // ["a", "b", "c", "d"]
// Flatten deeply nested (only one level)
const deepNested = [[[1, 2]], [[3, 4]]]
const oneLevelFlat = Iterable.flatten(deepNested)
console.log(Array.from(oneLevelFlat).map((arr) => Array.from(arr)))
// [[1, 2], [3, 4]] (still contains arrays)
// Empty iterables are handled correctly
const withEmpty = [[1, 2], [], [3, 4], []]
const flatWithEmpty = Iterable.flatten(withEmpty)
console.log(Array.from(flatWithEmpty)) // [1, 2, 3, 4]
flatten(const map: {
<A, B>(f: (a: NoInfer<A>, i: number) => B): (
self: Iterable<A>
) => Iterable<B>
<A, B>(
self: Iterable<A>,
f: (a: NoInfer<A>, i: number) => B
): Iterable<B>
}
map(self: Iterable<A>self, f: (a: A, i: number) => Iterable<B>f))
)