ts-tco
Version:
Utility for flattening tail recursion in TypeScript
53 lines (37 loc) • 1.13 kB
text/typescript
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);