# How to properly nest parametrically typed structs while using @kwdef

**URL:** <https://discourse.julialang.org/t/how-to-properly-nest-parametrically-typed-structs-while-using-kwdef/131036>\
**Category:** General Usage\
**Tags:** parametric-types, best-practices, advice\
**Created:** [July 24, 2025, 11:29pm UTC](https://discourse.julialang.org/t/how-to-properly-nest-parametrically-typed-structs-while-using-kwdef/131036 "2025-07-24T23:29:59Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![askprash](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/askprash/32/49806_2.png) [@askprash](https://discourse.julialang.org/u/askprash)\
**Post date:** [July 24, 2025, 11:29pm UTC](https://discourse.julialang.org/t/how-to-properly-nest-parametrically-typed-structs-while-using-kwdef/131036/1 "2025-07-24T23:29:59Z")

</div>

## How to use `@kwdef` with parametric structs and default constructors?

I’m trying to understand how to best use `@kwdef` with parametric structs in Julia, particularly when I want to define some default constructors and have those types nested in other custom types eventually.

Here’s an example. I’m defining some `AbstractThing` types, and then composing them into a larger struct `A_bigger_thing{T}`. I _want_ to use `@kwdef` to provide defaults, but I’m not sure I’m doing this in the right way.

#### MWE

```julia-auto
abstract type AbstractThing end

@kwdef struct Thing1 <: AbstractThing 
    x::Float64 = 0.0
end

@kwdef struct Thing2 <: AbstractThing 
    x::Float64 = 0.0
    y::Float64 = 1.0
end

# If I define this with @kwdef, I run into problems
# So I leave @kwdef off and write a manual outer constructor
mutable struct A_bigger_thing{T<:AbstractThing}
    thing::T
    value::Float64
end

# This works:
function A_bigger_thing{T}() where {T<:AbstractThing}
    A_bigger_thing{T}(T(), 0.0)
end

# Example usage:
# julia> A_bigger_thing{Thing1}()
# A_bigger_thing{Thing1}(Thing1(0.0), 0.0)

# julia> A_bigger_thing{Thing2}()
# A_bigger_thing{Thing2}(Thing2(0.0, 1.0), 0.0)

```

All this is fine, but I’m getting confused a little when I start to use `@kwdef` for convenience (in my real application there are 15 other fields that I provide defaults in the type definition).

For example, if I define `Another_bigger_thing` using `@kwdef`:

```julia-auto
@kwdef mutable struct Another_bigger_thing{T<:AbstractThing}
    thing::T
    value::Float64 = 1.0
end

```

I can instantiate them like:

```repl
julia> Another_bigger_thing(thing = Thing1())
Another_bigger_thing{Thing1}(Thing1(0.0), 1.0)

julia> Another_bigger_thing(thing = Thing2())
Another_bigger_thing{Thing2}(Thing2(0.0, 1.0), 1.0)

```

But what I’d _like_ is to be able to write is: `Another_bigger_thing{Thing1}()` because I want this to be a field in another struct, for example:

```julia
@kwdef mutable struct An_even_bigger_thing{T<:AbstractThing}
    value1::Float64 = 0.0
    value2::Float64 = 1.0
    big_thing::Another_bigger_thing{T} = Another_bigger_thing{T}()
end

```

So my approach was to define:

```julia-auto
function Another_bigger_thing{T}() where {T<:AbstractThing}
    Another_bigger_thing{T}(; thing = T())
end

```

### My Question

This seems to work, but I’m wondering:

- Is this a good way to combine `@kwdef` with parametric structs and default constructors?
- Is there a better way to support default construction (e.g., `Another_bigger_thing{T}()`) while still using keyword defaults via `@kwdef`?
- Are there any subtle pitfalls to this approach when used in larger codebases?

Thanks in advance for any guidance or best practices here!
