Recursive call vs while loop

It’s not enough that the function just return, to be tail recursive, a function must return a naked recursive call. The OP’s first example doesn’t return a naked call, transforms the result by multiplying it by N.

A tail recursive version of factorial would have to use an accumulator:

factorial(::Type{Val{0}}, acc) = acc
factorial(::Type{Val{N}}, acc) where N = factorial(Val{N - 1}, N * acc)
factorial(n) = factorial(Val{n}, 1)