A type-safe way to emulate tail-call optimization with trampolines
npm i trampoline-ts
# or
yarn add trampoline-ts
# or
pnpm add trampoline-ts
Requires a TypeScript version >= 3.0
import { trampoline, ThunkOrValue } from 'trampoline-ts';
const factorial = trampoline((n: number, acc: number = 1): ThunkOrValue<number> => {
return n
? // Note: calling factorial.cont instead of factorial directly
factorial.cont(n - 1, acc * n)
: acc;
});
factorial(32768); // No stack overflow
Takes a Tail Recursive Form function that returns a ThunkOrValue<T>
and
converts it to a tail-call optimized function. The returned function
Trampoline<F>
will have the exact same type signature as the passed
function except for one change, the return type will not contain
ThunkOrValue<T>
, it will just be T
.
It's important that fn
wraps the return type in ThunkOrValue
. If this is
omitted, TypeScript will not be able to infer the type of the returned
function and will default to any
.
Also note that to continue function recursion Trampoline<F>.cont()
should
be called, and not the function directly. .cont()
has the same type
signature as the passed function, so there's no way to call it incorrectly.
Same as trampoline
, but works with async/Promise-returning
functions.
A function that represents a tail-call optimized function.
An async function that represents a tail-call optimized function.
Function used to safely continue recursion. It captures F
's argument and
return types and thus has the same type signature.