First, there is another problem with your code. The constructor that should work with your definition is RegularGrid{Float64}((2,3)), i.e. with the dims specified as a tuple. However, this yields an error, because your type was defined as RegularGrid{N,T} with N first. But if you want an incomplete type specification with only T, you need to have T as first parameter (note AbstractArray{T,N}).
Then, to get the constructor you want, you need to use Vararg, but this does not need to be an inner constructor.
abstract type AbstractDomain{T<:Real,N} end
struct RegularGrid{T<:Real,N} <: AbstractDomain{T,N}
  dims::Dims{N}
  origin::NTuple{N,T}
  units::NTuple{N,T}
end
RegularGrid{T}(dims::Dims{N}) where {N,T<:Real} =
  RegularGrid{T,N}(dims, (zeros(T, length(dims))...), (ones(T, length(dims))...))
RegularGrid{T}(dims::Vararg{Int,N}) where {N,T<:Real} = RegularGrid{T}(dims)
Note that the last definition looks like it is calling itself. This is not true however. In the left, dims is a Vararg, i.e. multiple arguments. If you would not be interested in N, you could write it as dims::Int.... On the right hand side, when using the vararg dims in the function body, the different arguments to which it correspond will be collected in a tuple. Hense, on the right hand side dims is now NTuple{N,Int}===Dims{N}. This function call will then be passed on to the constructor you had written.