# Declare Union type as a function of which packages are installed

**URL:** <https://discourse.julialang.org/t/declare-union-type-as-a-function-of-which-packages-are-installed/22799>\
**Category:** General Usage\
**Tags:** parametric-types\
**Created:** [April 5, 2019, 1:23pm UTC](https://discourse.julialang.org/t/declare-union-type-as-a-function-of-which-packages-are-installed/22799 "2019-04-05T13:23:08Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![tpoisot](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tpoisot/32/19812_2.png) [@tpoisot](https://discourse.julialang.org/u/tpoisot)\
**Post date:** [April 5, 2019, 1:23pm UTC](https://discourse.julialang.org/t/declare-union-type-as-a-function-of-which-packages-are-installed/22799/1 "2019-04-05T13:23:08Z")

</div>

Here’s my use case: I have a series of parametric types, `Foo{T}`, and I would like them to accept different values of `T` depending on whether or not some packages are installed.

My current code is as follows:

```julia
_allowed_species_types = [String, Symbol, MangalNode, MangalReferenceTaxon]
try
  using GBIF
  push!(_allowed_species_types, GBIF.GBIFTaxon)
  @info "Package GBIF found: GBIFTaxon added as a species type"
catch
  nothing
end

"""
...
"""
AllowedSpeciesTypes = Union{_allowed_species_types...}

```

Is this the best way to proceed?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [April 5, 2019, 2:08pm UTC](https://discourse.julialang.org/t/declare-union-type-as-a-function-of-which-packages-are-installed/22799/2 "2019-04-05T14:08:06Z")

</div>

> [@tpoisot](#):
>
> Is this the best way to proceed?

Probably not; manipulating types themselves depending on (external) global state may be a suboptimal design.

Knowing more about the context (what you are trying to do) could lead to better suggestions.

---

<div class="post-metadata">

**Author:** ![tpoisot](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tpoisot/32/19812_2.png) [@tpoisot](https://discourse.julialang.org/u/tpoisot)\
**Post date:** [April 5, 2019, 3:56pm UTC](https://discourse.julialang.org/t/declare-union-type-as-a-function-of-which-packages-are-installed/22799/3 "2019-04-05T15:56:17Z")

</div>

I have graphs, and nodes can have different types. But I want to restrict these types somehow, or allow some types to be used as nodes.

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [April 5, 2019, 4:55pm UTC](https://discourse.julialang.org/t/declare-union-type-as-a-function-of-which-packages-are-installed/22799/4 "2019-04-05T16:55:55Z")

</div>

The problem with making the type definition conditional is that it’s going to make your code hard to reason about and potentially dependent on the order in which you load or install packages.

Instead, how about this:

Drop the restriction on `T` entirely, and just let it be anything as far as the type definition is concerned. Your struct should look like:

```julia
struct Foo{T}
  x::T
  function Foo{T}(x::T) where {T}
     ... inner constructor goes here...
  end
end

```

Then, in the inner constructor, add a check like this:

```julia
is_allowed(T) || throw(ArgumentError("Not allowed"))

```

Now you need to define:

```julia
is_allowed(::Type{T}) where {T} = false
is_allowed(::Type{String}) = true

```

For types you want to conditionally allow, use Requires.jl to do (roughly):

```julia
@require OtherPackage begin
  is_allowed(::Type{OtherPackage.Foo}) = true
end

```

This will give you good performance (the `is_allowed` check can likely be optimized away by the compiler) and no weird dependency on load order.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [April 5, 2019, 4:57pm UTC](https://discourse.julialang.org/t/declare-union-type-as-a-function-of-which-packages-are-installed/22799/5 "2019-04-05T16:57:25Z")

</div>

Either use subtyping (all have a common abstract supertype) , duck typing (no type restriction), or verify something at runtime. I would very much discourage trying to do almost anything based on what packages happen to be installed and especially try to constrain types based on it.
