Okay! I managed to find a remarkably clean way to do this!! I’ve also seen other threads of people who want to do something similar (and it turns out there is a Mixers.jl package that can be used to do what it is that I’m doing, but in my opinion, this method looks more intuitive). Anyway, the key step was to infer whether the FieldType was a Symbol, a non-parametric type or a parametric type. I also learned I could get the actual constructer of a type from the “.name.wrapper” field and get the parameters from the “.parameter” field too. Once this “get_type_expression” function worked, everything else fell into place.
function get_type_expression(X::Union{Symbol,DataType})
if X isa Symbol
return X
elseif X isa DataType
Params = X.parameters
if isempty(Params)
return Symbol(X.name.wrapper)
else
return Expr(:curly, Symbol(X.name.wrapper), Params...)
end
end
end
macro inherit_asset_fields(AssetTypeExp::Expr)
BaseAssetType = Core.eval(@__MODULE__, AssetTypeExp.args[1])
TypeSymbols = AssetTypeExp.args[2:end]
AssetType = BaseAssetType{TypeSymbols...}
ex = Expr(:block)
for fName in filter( x-> x!=:Specs, fieldnames(AssetType) )
fType = fieldtype(AssetType, fName)
fTypeParsed = get_type_expression(fType)
push!(ex.args, :( $fName :: $fTypeParsed ) )
end
return esc(ex)
end
mutable struct MyOldType{T}
Name :: Symbol
A :: T
B :: T
V :: Vector{T}
Specs :: String
end
mutable struct MyNewType{T}
@inherit_asset_fields(MyOldType{T})
C :: T
NewSpecs::String
end