UNPKG

ts-tco

Version:

Utility for flattening tail recursion in TypeScript

53 lines (37 loc) 1.13 kB
export const executeTco = <T>(v: TcoLike<T>): T => { let value: TcoLike<unknown> = v; let maps: Array<(v: unknown) => TcoLike<unknown>> = []; while (value instanceof Tco || value instanceof TcoThen || maps.length) if (value instanceof TcoThen) { maps.unshift(value.func); value = value.from; } else if (value instanceof Tco) { value = value.func(); } else if (maps.length) { value = maps.shift()?.(value); } return value as T; } export class Tco<T> { constructor(public func: TcoFunc<T>) { } execute(): T { return executeTco(this); } then<U>(func: (val: T) => TcoLike<U>): TcoThen<T, U> { return new TcoThen(this, func); } } export class TcoThen<T, U> { constructor(public from: TcoLike<T>, public func: (val: T) => TcoLike<U>) { } execute(): U { return executeTco(this); } then<V>(func: (val: U) => TcoLike<V>): TcoThen<U, V> { return new TcoThen(this, func); } } export type TcoLike<T> = T | Tco<T> | TcoThen<any, T>; export type TcoFunc<T> = () => TcoLike<T>; export const tco = <T extends any>(f: TcoFunc<T>) => new Tco(f);