This issue doesn’t really involve convert or nested types, that part is actually fine here. Parametric type definitions just don’t automatically make the parameter-less constructor methods that many people want. You have to define them yourself, which you did.
julia> struct MyType
x::Float64
end
julia> methods(MyType) # one for known field, one for conversions
# 2 methods for type constructor:
[1] MyType(x::Float64)
@ REPL[13]:2
[2] MyType(x)
@ REPL[13]:2
julia> struct MyType2{T} # useless parameter
x::Float64
end
julia> methods(MyType2) # all gone!
# 0 methods for type constructor
julia> methods(MyType2.body) # parametric constructor still here
# 1 method for type constructor:
[1] (var"#ctor-self#"::Type{MyType2{T}} where T)(x)
@ REPL[16]:2
The equivalent approach to what you demonstrated would be:
MyType2(x::T) where T = MyType{T}(x)
You might spot the problem here: T is a useless parameter and x would be converted to Float64 prior to successful instantiation, so there’s no reason for T to match typeof(x). We don’t need MyType2{Int64}(1.0), in fact we’d have more type stability if we just instantiated MyType{Float64}(x). There isn’t a good automatic way to compute type parameters entirely from inputs. A more practical but complex example would be inputs with different types for fields that share only 1 parameter; it’s not clear if promotion is desired, and you’d still have to implement promote yourself. I think there is an issue about adding these default constructors anyway, letting us opt out manually like usual, that ended up saying it’d be breaking.