How to parameterize a type on dimensionality of the wrapped array?

Struggling a bit with parametric types for TiffImages.jl. I want to have two different types of DenseTaggedImage for 2D and 3D images since the ifd variable is a vector for 3D images and 0-dimensional for 2D images.

julia> abstract type AbstractTIFF{T, N} <: AbstractArray{T, N} end

julia> abstract type AbstractDenseTIFF{T, N} <: AbstractTIFF{T, N} end

julia> struct IFD{O <: Unsigned} end

julia> struct DenseTaggedImage{T, O <: Unsigned, AA <: AbstractArray{T, 3}} <: AbstractDenseTIFF{T, 3}
           data::AA
           ifd::Vector{IFD{O}}
       end

julia> struct DenseTaggedImage{T, O <: Unsigned, AA <: AbstractArray{T, 2}} <: AbstractDenseTIFF{T, 2}
           data::AA
           ifd::IFD{O}
       end
ERROR: invalid redefinition of constant DenseTaggedImage
Stacktrace:
 [1] top-level scope
   @ REPL[5]:1

I thought adding the dimension to the AbstractArray parameter and to the subtyping info would be sufficient to create a new type, but I’m still getting a redefinition error. Where did I go wrong here?

I used to have a single type for both 2D and 3D arrays: https://github.com/tlnagy/TiffImages.jl/blob/70e14527c97cc019f71abdb4ab0d98416f9187b2/src/types/dense.jl#L3-L17

One possibility is to parametrize the complete type of ifd and put the dimension as the first parameter for dispatch. Maybe that is simpler. Something like: