Sorry, this title isn’t great but not sure what to put there

I am working on the parallel type hierarchy that’s part of ScientificTypes.jl and we have a function `Scitype`

that maps types to types. I want the following covariance properties:

- the
`Scitype`

of a`Tuple`

type should be the`Tuple`

of the`Scitypes`

- the
`Scitype`

of a (finite)`Union`

should be the`Union`

of the`Scitypes`

My naive way of implementing 1. works as expected:

```
Scitype(::Type{Tuple{A,B}}) where {A,B} = Tuple{Scitype(A),Scitype(B)}
```

To see this, suppose we have

```
abstract type Continuous end
abstract type Count end
Scitype(::Type{<:Integer}) = Count
Scitype(::Type{<:AbstractFloat}) = Continuous
```

Then

```
julia> Scitype(Tuple{Int,Float64})
Tuple{Count, Continuous}
```

However, mimicking this for union types throws a curious error:

```
Scitype(::Type{Union{A,B}}) where {A,B} = Union{Scitype(A),Scitype(B)}
julia> Scitype(Union{Int,Float64})
ERROR: UndefVarError: B not defined
Stacktrace:
[1] Scitype(#unused#::Type{Union{Float64, Int64}})
@ Main ./REPL[13]:1
[2] top-level scope
@ REPL[14]:1
```

I realize tuples and unions are different, and am reluctant to call this a bug. But I wonder how I should implement what I want here. The following works

```
Scitype(u::Union) = Union{Scitype(u.a),Scitype(u.b)}
```

but that looks like using non-public interface.

cc @samuel_okon