Sequences represent lazy operations on collections, allowing efficient chaining of transformations without creating intermediate collections. Sequences are immutable and can be cached for performance.
import { Seq, Range, Repeat } from 'immutable';abstract class Seq<K, V> implements Collection<K, V> {
static <K, V>(collection: Collection<K, V>): Seq<K, V>;
static <T>(collection: Iterable<T>): Seq.Indexed<T>;
static <V>(obj: {[key: string]: V}): Seq.Keyed<string, V>;
static isSeq(maybeSeq: unknown): maybeSeq is Seq<unknown, unknown>;
// Properties
size: number | undefined; // May be lazily computed or undefined
// Force evaluation
cacheResult(): Seq<K, V>;
// All Collection methods inherited
}Sequences with key-value pairs, similar to Object iteration.
namespace Seq {
class Keyed<K, V> extends Seq<K, V> {
// Factory methods
static <K, V>(collection?: Collection.Keyed<K, V>): Seq.Keyed<K, V>;
static <V>(obj: {[key: string]: V}): Seq.Keyed<string, V>;
// Conversion
toJS(): {[key: string]: unknown};
toJSON(): {[key: string]: V};
toArray(): Array<[K, V]>;
toSeq(): Seq.Keyed<K, V>;
// Sequence operations
concat(...collections: Array<Iterable<[K, V]> | {[key: string]: V}>): Seq.Keyed<K, V>;
map<M>(mapper: (value: V, key: K, iter: this) => M, context?: unknown): Seq.Keyed<K, M>;
mapKeys<M>(mapper: (key: K, value: V, iter: this) => M, context?: unknown): Seq.Keyed<M, V>;
mapEntries<KM, VM>(mapper: (entry: [K, V], index: number, iter: this) => [KM, VM], context?: unknown): Seq.Keyed<KM, VM>;
flatMap<KM, VM>(mapper: (value: V, key: K, iter: this) => Iterable<[KM, VM]>, context?: unknown): Seq.Keyed<KM, VM>;
filter(predicate: (value: V, key: K, iter: this) => boolean, context?: unknown): Seq.Keyed<K, V>;
partition(predicate: (value: V, key: K, iter: this) => boolean, context?: unknown): [Seq.Keyed<K, V>, Seq.Keyed<K, V>];
flip(): Seq.Keyed<V, K>;
// Iterator
[Symbol.iterator](): IterableIterator<[K, V]>;
}
}import { Seq } from 'immutable';
// Create from object
const keyedSeq = Seq.Keyed({ a: 1, b: 2, c: 3 });
// Lazy operations
const transformed = keyedSeq
.map(value => value * 2)
.filter(value => value > 2)
.mapKeys(key => key.toUpperCase());
// Force evaluation
const result = transformed.toObject(); // { B: 4, C: 6 }
// Chain operations efficiently
const complex = Seq.Keyed({ x: 1, y: 2, z: 3 })
.mapEntries(([key, value]) => [key + '_new', value * 10])
.flip()
.toMap(); // Map { 10: 'x_new', 20: 'y_new', 30: 'z_new' }Sequences with numeric indices, similar to Array iteration.
namespace Seq {
class Indexed<T> extends Seq<number, T> {
// Factory methods
static <T>(collection?: Collection.Indexed<T>): Seq.Indexed<T>;
static of<T>(...values: T[]): Seq.Indexed<T>;
// Conversion
toJS(): unknown[];
toJSON(): T[];
toArray(): T[];
toSeq(): Seq.Indexed<T>;
// Sequence operations
concat(...valuesOrCollections: Array<T | Iterable<T>>): Seq.Indexed<T>;
map<M>(mapper: (value: T, index: number, iter: this) => M, context?: unknown): Seq.Indexed<M>;
flatMap<M>(mapper: (value: T, index: number, iter: this) => Iterable<M>, context?: unknown): Seq.Indexed<M>;
filter(predicate: (value: T, index: number, iter: this) => boolean, context?: unknown): Seq.Indexed<T>;
partition(predicate: (value: T, index: number, iter: this) => boolean, context?: unknown): [Seq.Indexed<T>, Seq.Indexed<T>];
zip<U>(other: Collection<unknown, U>): Seq.Indexed<[T, U]>;
zipAll<U>(other: Collection<unknown, U>): Seq.Indexed<[T, U]>;
zipWith<U, Z>(zipper: (value: T, otherValue: U) => Z, otherCollection: Collection<unknown, U>): Seq.Indexed<Z>;
// Iterator
[Symbol.iterator](): IterableIterator<T>;
}
}import { Seq } from 'immutable';
// Create from array
const indexedSeq = Seq.Indexed([1, 2, 3, 4, 5]);
// Lazy operations
const transformed = indexedSeq
.map(x => x * x)
.filter(x => x > 5)
.take(3);
// Force evaluation
const result = transformed.toArray(); // [9, 16, 25]
// Zip operations
const seq1 = Seq.Indexed([1, 2, 3]);
const seq2 = Seq.Indexed(['a', 'b', 'c']);
const zipped = seq1.zip(seq2).toArray(); // [[1, 'a'], [2, 'b'], [3, 'c']]
// Custom zip function
const customZipped = seq1.zipWith((num, str) => `${num}-${str}`, seq2);
console.log(customZipped.toArray()); // ['1-a', '2-b', '3-c']Sequences with unique values, similar to Set iteration.
namespace Seq {
class Set<T> extends Seq<T, T> {
// Factory methods
static <T>(collection?: Collection.Set<T>): Seq.Set<T>;
static of<T>(...values: T[]): Seq.Set<T>;
// Conversion
toJS(): unknown[];
toJSON(): T[];
toArray(): T[];
toSeq(): Seq.Set<T>;
// Sequence operations
concat(...collections: Array<Iterable<T>>): Seq.Set<T>;
map<M>(mapper: (value: T, value2: T, iter: this) => M, context?: unknown): Seq.Set<M>;
flatMap<M>(mapper: (value: T, value2: T, iter: this) => Iterable<M>, context?: unknown): Seq.Set<M>;
filter(predicate: (value: T, value2: T, iter: this) => boolean, context?: unknown): Seq.Set<T>;
partition(predicate: (value: T, value2: T, iter: this) => boolean, context?: unknown): [Seq.Set<T>, Seq.Set<T>];
// Iterator
[Symbol.iterator](): IterableIterator<T>;
}
}import { Seq, Set } from 'immutable';
// Create from Set or array with duplicates
const setSeq = Seq.Set([1, 2, 2, 3, 3, 4]);
// Lazy operations maintain uniqueness
const transformed = setSeq
.map(x => x * 2)
.filter(x => x > 4);
// Force evaluation
const result = transformed.toArray(); // [6, 8]
// Convert to other collections
const backToSet = transformed.toSet(); // Set { 6, 8 }
const toList = transformed.toList(); // List [ 6, 8 ]Creates sequences of numbers.
function Range(start?: number, end?: number, step?: number): Seq.Indexed<number>;start (optional): Starting number (default: 0)end (optional): Ending number (exclusive, default: Infinity)step (optional): Step size (default: 1)import { Range } from 'immutable';
// Basic ranges
const range1 = Range(10); // [0, 1, 2, ..., 9]
const range2 = Range(5, 10); // [5, 6, 7, 8, 9]
const range3 = Range(0, 10, 2); // [0, 2, 4, 6, 8]
// Infinite sequences (be careful!)
const infinite = Range(0); // [0, 1, 2, 3, ...]
const first5 = infinite.take(5).toArray(); // [0, 1, 2, 3, 4]
// Reverse ranges
const reverse = Range(10, 0, -1); // [10, 9, 8, ..., 1]
// Complex operations
const processed = Range(1, 100)
.filter(n => n % 2 === 0)
.map(n => n * n)
.take(5)
.toArray(); // [4, 16, 36, 64, 100]Creates sequences of repeated values.
function Repeat<T>(value: T, times?: number): Seq.Indexed<T>;value: The value to repeattimes (optional): Number of repetitions (default: Infinity)import { Repeat } from 'immutable';
// Finite repetition
const repeat1 = Repeat('hello', 3); // ['hello', 'hello', 'hello']
const repeat2 = Repeat(42, 5); // [42, 42, 42, 42, 42]
// Infinite repetition (be careful!)
const infinite = Repeat('x'); // ['x', 'x', 'x', ...]
const first3 = infinite.take(3).toArray(); // ['x', 'x', 'x']
// Complex values
const complexRepeat = Repeat({ id: 1, name: 'test' }, 2);
const result = complexRepeat.toArray(); // [{ id: 1, name: 'test' }, { id: 1, name: 'test' }]
// With transformations
const transformed = Repeat(1, 5)
.map((val, index) => val + index)
.toArray(); // [1, 2, 3, 4, 5]Sequences are evaluated lazily, meaning operations are not performed until the sequence is consumed:
interface Seq<K, V> {
cacheResult(): Seq<K, V>;
}import { Seq } from 'immutable';
// Operations are not executed until consumption
const lazySeq = Seq([1, 2, 3, 4, 5])
.map(x => {
console.log(`Processing ${x}`); // Not executed yet
return x * 2;
})
.filter(x => x > 5);
// Force evaluation and cache result
const cached = lazySeq.cacheResult();
// Multiple consumptions use cached result
const array1 = cached.toArray(); // Logs: Processing 1, 2, 3, 4, 5
const array2 = cached.toArray(); // No logging, uses cached result
// Without caching, each consumption re-evaluates
const uncached = Seq([1, 2, 3]).map(x => x * 2);
const result1 = uncached.toArray(); // Evaluates
const result2 = uncached.toArray(); // Evaluates againSequences can be converted to collections or JavaScript types:
interface Seq<K, V> {
// To Collections
toList(): List<V>;
toMap(): Map<K, V>;
toOrderedMap(): OrderedMap<K, V>;
toSet(): Set<V>;
toOrderedSet(): OrderedSet<V>;
toStack(): Stack<V>;
// To JavaScript
toJS(): unknown;
toJSON(): unknown;
toArray(): unknown[];
toObject(): {[key: string]: V};
}import { Seq, List, Map, Set } from 'immutable';
const seq = Seq({ a: 1, b: 2, c: 3 })
.map(value => value * 2)
.filter(value => value > 2);
// Convert to different collection types
const list = seq.toList(); // List [ 4, 6 ]
const map = seq.toMap(); // Map { "b" => 4, "c" => 6 }
const set = seq.valueSeq().toSet(); // Set { 4, 6 }
// Convert to JavaScript types
const obj = seq.toObject(); // { b: 4, c: 6 }
const arr = seq.entrySeq().toArray(); // [['b', 4], ['c', 6]]
const js = seq.toJS(); // { b: 4, c: 6 }Sequences are designed for efficient chaining:
import { List, Seq } from 'immutable';
const list = List([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
// Inefficient: Creates intermediate collections
const inefficient = list
.map(x => x * 2) // Creates new List
.filter(x => x > 10) // Creates new List
.take(3); // Creates new List
// Efficient: Uses lazy evaluation
const efficient = list
.toSeq() // Convert to Seq
.map(x => x * 2) // Lazy operation
.filter(x => x > 10) // Lazy operation
.take(3) // Lazy operation
.toList(); // Single evaluation
// Even more efficient for one-time use
const oneTime = Seq(list)
.map(x => x * 2)
.filter(x => x > 10)
.take(3)
.toArray(); // Direct to JavaScript array