In general, overloading Base methods with custom types is very much intended. Type piracy is pretty discouraged, though. (type piracy = overloading methods owned by other modules with types that are not owned by your module)
This specific case is unfortunately bad, because it does not compose:
julia> struct Blag2 end
julia> Base.promote_typejoin(::Type{Blag2}, ::Type{T}) where {T} =
isconcretetype(T) || T === Union{} ? Union{T, Blag2} : Any
julia> Base.promote_typejoin(::Type{T}, ::Type{Blag2}) where {T} =
isconcretetype(T) || T === Union{} ? Union{T, Blag2} : Any
julia> typeof([ifelse(randn() < 0, Blag(), Blag2()) for _ in 1:100])
ERROR: MethodError: promote_typejoin(::Type{Blag2}, ::Type{Blag}) is ambiguous. Candidates:
promote_typejoin(::Type{T}, ::Type{Blag}) where T in Main at REPL[4]:1
promote_typejoin(::Type{Blag2}, ::Type{T}) where T in Main at REPL[13]:1
This is not really bad type piracy (changing behavior of unrelated code just by loading your module), but it is not pretty either (two independent modules might interact suboptimally – i.e. it is up to people who want to (transitively) import both Blag and Blag2 to resolve the conflict, and this resolution must engage in actual “officially discouraged” type piracy)