struct Lattice{D, L, D1}
# number of sites per dimension
L::NTuple{D, Int}
...
sites::Array{Site{L}, D1}
end

where D is just the dimension of the lattice and D1 is D+1. Since D1 is related to D there should be a way of writing this structure without D1, right? Thanks for any help

The short answer is that there isnāt. The solution StaticArrays uses is to have extra type parameters, but to define a constructor that means users donāt have to use the extra ones.

mutable struct Foo{N}
x::Array{Float64,N}
s::NTuple{N+1,Int64}
function Foo(arraysize,extradimsize=10)
nD = length(arraysize)
x = rand((arraysize...,extradimsize)...)
s = (arraysize...,extradimsize)
new{nD}(x,s)
end
end

I am a bit hesitant to add a dependency for it, but on the other side it seems a bit ācomplexā to use metaprogramming for itā¦ can you just confirm there isnāt a simple solution for it ?

There is actually a trivial solution for you (though it does not fully generalize) for adding constants (whereas the original question was about subtraction):

s::Tuple{Int,Vararg{Int,N}}

or, similarly for multiplication:

t::NTuple{N,NTuple{N,Int}} # total element count is N^2

There is indeed no way to get rid of an extra parameter to the outer struct if you want to have some type parameter in an inner field that is based on some computation of the outer parameter, no matter how trivial the computation is.