How to balance the variants type in the simple case below:

function dev(X::Number)
return diff(X)
end

if Julia derivatives X with respect to X returns 1.0?

ERROR: LoadError: MethodError: no method matching diff(::Float64)
Closest candidates are:
diff(!Matched::AbstractRange{T}; dims) where T at multidimensional.jl:851
diff(!Matched::SparseArrays.AbstractSparseMatrixCSC; dims) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/SparseArrays/src/linalg.jl:1068
diff(!Matched::AbstractArray{T,1} where T) at multidimensional.jl:809

I would say that ForwardDiff computes the exact symbolic derivative, though you can only directly access the result evaluated using floating-point arithmetic. If you look at the assembly code the compiler generates from ForwardDiff, it contains the exact symbolic derivative formula; for example, here it is computing that the derivative of x^2 is 2x:

Whereas “numerical derivatives” typically refer to approximate derivative formulas obtained from a sequence of function values only, such as those computed by FiniteDifferences.jl.

Most automatic differentiation systems take the point of view that they can essentially return anything at a non-differentiable point, and should prefer to return a value that is useful. There’s currently a ChainRulesCore.jl pull request to document this convention, here is a preview of the proposed documentation.