One design pattern I keep stumbling upon is that I want to generate parametric types based on existing parametric types, but with certain constraints among parameters, such that inappropriate combinations are prevented from ever being defined by the user (and causing further trouble).

For example, let’s say I have types `Type1{S}`

and `Type2{S,T}`

and I want to define a new type `Type3{U,V}`

such that `U<:Type1{S}`

and `V<:Type2{S,T}`

, but in addition I want to enforce that the parameter `S`

in both parameters is the same. I.e. trying to call or define a `Type3{U,V}`

for some `U<:Type1{S}`

and `V<:Type2{S2,T}`

will produce an error whenever `S`

and `S2`

are different.

The problem I have is that I do not really know how to create such types in a Julia-paradigmatic way, or even whether this is the best way to solve the problem I have (i.e. excluding types with inconsistent parameters to exist).

When I want `Type3`

to be an abstract type, I can do

```
# correct syntax, but not the desired result
abstract type Type3{U<:Type1{S} where S, V<:Type2{S,T} where {S, T}} end
```

but this does not force the `S`

in both `U`

and `V`

to be the same.

The following does *not* work, but should give a flavor of what I’m trying to do:

```
# throws error `syntax: invalid type signature`
abstract type Type3{U<:Type1{S}, V<:Type2{S,T}} where {S,T} end
```

The following works for structs, but is probably a bit too convoluted (especially if the pattern keeps coming up), and cannot be done for abstract types because they lack constructors:

```
# correct syntax and outcome
struct Type3{S, T, U, V}
x::U
y::V
Type3(x::Type1{S}, y::Type2{S,T}) where {S, T} = new{S, T, typeof(x), typeof(y)}(x, y)
end
```

Slightly simpler would be the following (which again does *not* work):

```
# throws error `syntax: invalid type signature`
struct Type3{U<:Type1{S}, V<:Type2{S, T} where {S, T}
x::U
y::V
end
```