I have a set of types that are related, e.g. by composition, but also logically (eg one can be converted to another).

I have a parallel set of types that satisfy the same relations.

I’d like to put as much as possible in an abstract interface. Here is an example:

```
abstract type AbstractT1 end
abstract type AbstractT2 end
struct A1 <: AbstractT1
x::Int
end
struct A2 <: AbstractT2
a1::A1
end
struct B1 <: AbstractT1
x::Int
end
struct B2 <: AbstractT2
b1::B1
end
outer_type(::Type{A1}) = A2
outer_type(::Type{B1}) = B2
function double_T2(t1::T) where {T <: AbstractT1}
return outer_type(T)(T(2 * t1.x))
end
```

```
julia> double_T2(A1(2))
A2(A1(4))
julia> double_T2(B1(3))
B2(B1(6))
```

In my actual use case, there are more types with more complex realtionships in each set. There are also more than two sets. I am currently using more functions like `outer_type`

.

Something tells me that I am missing a more elegant way to do this. Has anyone run into this before ?