Using of non exported functions of Base in package code

During the development of a package I needed some reflective informations of a Union datatype. I used the following formulation:

Optional{T} = Union{Nothing, T}

struct Address
   street::String
   town::String
end

struct TestStruct
   address::Optional{Address}
end

in one of the package functions I need to know which Type besides Nothing is inside the Union type. For this I used Base.uniontypes. My question is now: Is there any other way to get the datatypes besides what I used and is it appropriate to use non exported functions if they fits very well?
Opinions and suggestions are highly appreciated.

Why doesn’t f(::Optional{T}) where {T} = T work?

1 Like

Well, I’ve tried your suggestion but I get only the Union type back. What I’m Interested in is the type T itself. I you use your suggestion you will get the following:
f(::Optional{T}) where {T} = T with Optional{String} gives Union and I’m interested in String.

The idea is to call this f with a value of type Optional{T}, for example f("xxx") (because "xxx" is a String which is an Optional{T} with T=String.

If what you want is to pass the type Optional{T} and get back T, then define:

f(::Type{Optional{T}}) where {T} = T

which gives:

julia> f(Optional{Int})
Int64

julia> f(Optional{String})
String
1 Like

Note that you then have:

julia> f(Nothing)
ERROR: UndefVarError: T not defined

so you might want to decide on how to handle the nothing case in there too. For example:

julia> f(::Type{Optional{T}}) where {T} = (@isdefined T) ? T : nothing
f (generic function with 1 method)

julia> f(Optional{Int})
Int64

julia> f(Optional{String})
String

julia> f(Nothing)
nothing
1 Like

It seems a lot easier to handle this by just defining

f(::Type{Optional{T}}) where {T} = T
f(::Type{Nothing}) = nothing

rather than using @isdefined.

4 Likes

Thanks for your explanations. Many learned. :+1: :smiley: