# Parametric constructors

**URL:** <https://discourse.julialang.org/t/parametric-constructors/125526>\
**Category:** General Usage\
**Created:** [February 4, 2025, 10:32am UTC](https://discourse.julialang.org/t/parametric-constructors/125526 "2025-02-04T10:32:59Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![azoviktor](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/azoviktor/32/206405_2.png) [@azoviktor](https://discourse.julialang.org/u/azoviktor)\
**Post date:** [February 4, 2025, 10:32am UTC](https://discourse.julialang.org/t/parametric-constructors/125526/1 "2025-02-04T10:32:59Z")

</div>

I have a parametric type

```julia
struct MyStruct{T <: Real, S}
    x::T
    y::S
end

```

and I have an outer constructor like

```julia
MyStruct{S}(x, y) where {S} = MyStruct{typeof(x), S}(x, y)

```

If I run

```julia-repl
julia> MyStruct{Float32}(2.0, 3.0)
MyStruct{Float64, Float32}(2.0, 3.0f0)

```

everything is OK. If I run

```julia-repl
julia> MyStruct{String}(2.0, "s")
ERROR: TypeError: in MyStruct, in T, expected T<:Real, got Type{String}

```

it results in the error. What is happening here?

Even if I don’t define an outer constructor written above, in julia repl I get the following

```julia-repl
julia> MyStruct{Float32}
MyStruct{Float32}

julia> MyStruct{String}
ERROR: TypeError: in MyStruct, in T, expected T<:Real, got Type{String}

```

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [February 4, 2025, 10:46am UTC](https://discourse.julialang.org/t/parametric-constructors/125526/2 "2025-02-04T10:46:29Z")

</div>

It errors at `MyStruct{String}` alone. When you provide M\<N parameters for a struct with N parameters, it makes an iterated union that fills in the first M parameters and takes the bounds of the type for the rest:

```julia
julia> MyStruct{Float64} == MyStruct{Float64, <:Any}
true

```

I see what you’re trying to do, but it’s not possible to opt out of the type system’s behavior above and treat `S` as an extra input next to the name `MyStruct`. An iterated union with the type parameter in the right position would work:

```julia
julia> MyStruct{<:Real, S}(x, y) where {S} = MyStruct{typeof(x), S}(x, y)

julia> MyStruct{<:Real, String}(2, "a")
MyStruct{Int64, String}(2, "a")

```

but that’s wordier. Any dummy type parameter or bounds there would still instantiate properly, but `<:Real` is more consistent with the iterated unions that setting M parameters would make.

---

<div class="post-metadata">

**Author:** ![azoviktor](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/azoviktor/32/206405_2.png) [@azoviktor](https://discourse.julialang.org/u/azoviktor)\
**Post date:** [February 4, 2025, 11:15am UTC](https://discourse.julialang.org/t/parametric-constructors/125526/3 "2025-02-04T11:15:49Z")

</div>

Thanks, didn’t know that `MyStruct{Float64}` is indeed of UnionAll type.

What if now I have a struct

```julia
struct MyStruct{T<:Real}
    x::T
end

```

Now I got curious: what does `MyStruct{<:Any}` really generate? I feel like it should be a union of all types of the form `MyStruct{T}`, where `T<:Any`. But then the type `MyStruct{String}` should be in this union as well (however, it cannot be created in Julia REPL).

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [February 4, 2025, 11:23am UTC](https://discourse.julialang.org/t/parametric-constructors/125526/4 "2025-02-04T11:23:19Z")

</div>

Right, you can make iterated unions that specify invalid types, even strict supertypes of the original type or a completely disjoint set of invalid types:

```julia
julia> struct Blah{X<:Int} end

julia> Blah <: Blah{<:Any}
true

julia> Blah >: Blah{<:Any}
false

julia> Blah <: Blah{<:String}
false

julia> Blah >: Blah{<:String}
false

```
