// "typesafe" lazy iteration functions export function map(fn: (value: T, idx: number) => U) { return function* (iter: Iterable) { let idx = 0 for (let value of iter) { yield fn(value, idx) idx += 1 } } } export function filter(fn: (value: T) => value is S): (iter: Iterable) => Generator; export function filter(fn: (value: T) => unknown): (iter: Iterable) => Generator export function filter(fn: (value: T) => unknown) { return function* (iter: Iterable) { for (let value of iter) { if (fn(value)) { yield value } } } } export function take(n: number) { return function* (iter: Iterable): Generator { let count = n - 1 for (let value of iter) { if (count <= 0) { break } yield value count -= 1 } } } export function skip(n: number) { return function* (iter: Iterable): Generator { let count = n - 1 for (let value of iter) { if (count >= 0) { count = count - 1 continue } yield value } } } type unshift = ((arg: T, ...rest: U) => void) extends ((...args: infer X) => void) ? X : never type LazyIterator = (iter: Iterable) => Generator type composition2 = [LazyIterator, LazyIterator] type composition3 = unshift, composition2> type composition4 = unshift, composition3> type composition5 = unshift, composition4> type composition6 = unshift, composition5> export function compose(...args: composition2): LazyIterator; export function compose(...args: composition3): LazyIterator; export function compose(...args: composition4): LazyIterator export function compose(...args: composition5): LazyIterator export function compose(...args: composition6): LazyIterator export function compose(init: LazyIterator, ...rest: Array>) { return function (iter: Iterable) { return rest.reduce((acc, gen) => gen(acc), init(iter)) } }