type ArrayBranch<B, L> = [B, ...(L | ArrayBranch<B, L>)[]]
type ArrayTree<B, L> = L | ArrayBranch<B, L>
function isLeaf<B, L>(n: ArrayTree<B, L>): n is L {return !(n instanceof Array)}
function value<B, L>(n: ArrayBranch<B,L>): B { return n[0] }
function construct<B, L>(b: B, branches: (L | ArrayBranch<B, L>)[]): ArrayBranch<B, L> { return [b, ...branches] }
function attach<B, L>(n: ArrayBranch<B, L>, branches: (L | ArrayBranch<B, L>)[]): ArrayBranch<B, L> { return [...n, ...branches]}
function branch<B, L>(n: L | ArrayBranch<B, L>): (L | ArrayBranch<B, L>)[] {
if (isLeaf(n)) return []
const [_, ...rest] = n
return rest
}
function postwalk<H, T>(f: (t: ArrayBranch<H, T>) => ArrayTree<H, T>, tree: T): T
function postwalk<H, T>(f: (t: ArrayBranch<H, T>) => ArrayTree<H, T>, tree: ArrayBranch<H,T>): ArrayBranch<H, T>
function postwalk<H, T>(f: (t: ArrayBranch<H, T>) => ArrayBranch<H, T>, tree: ArrayTree<H,T>): ArrayTree<H, T> {
// yield processed nodes in pre-walk order, transforming the *processed* child nodes,
// not the original node. Excludes leaf nodes (those require a ArrayTree => ArrayTree transformation)
if (isLeaf(tree)) return tree
const branches = branch(tree).map((x) => postwalk(f, x))
return f(construct(value(tree), branches))
}
function prewalk<H, T>(f: (t: ArrayBranch<H, T>) => ArrayTree<H, T>, tree: T): T
function prewalk<H, T>(f: (t: ArrayBranch<H, T>) => ArrayTree<H, T>, tree: ArrayBranch<H,T>): ArrayBranch<H, T>
function prewalk<H, T>(f: (t: ArrayBranch<H, T>) => ArrayTree<H, T>, tree: ArrayTree<H,T>): ArrayTree<H, T> {
if (isLeaf(tree)) return tree
let n = f(tree)
if (isLeaf(n)) return n
const b = branch(n)
if (b) {
n = attach(n, b.map((t: ArrayTree<H, T>) => prewalk(f, t)))
}
return n
}
The recursive call shows an error on both prewalk and postwalk.
I don't get why because I have both cases covered in the signature.
Do I need conditional types? if so how do I do that?