I also didn’t know about typejoin which solves the problem!
One small issue with the proposed solution though is that convert(Foo{T}, f::Foo) isn’t guaranteed to return a value of type Foo{T}. E.g. convert(Foo{Any}, Foo(1)) returns Foo{Int64}(1) which is not a Foo{Any}. So I suppose the correct thing would be to define Base.convert(::Type{Foo{T}}, f::Foo) where {T} = Foo{T}(f.x)