You could do something like the following:
abstract type model_A end
struct params1 <: model_A
a::Float64
params1(a::Number) = new(a)
end
struct params2 <: model_A
a::Float64
b::Float64
params2(a::Number, b::Number) = new(a, b)
end
function (::Type{P})(args...) where P <: model_A
[P(params...) for params in Iterators.product(args...)]
end
Then you get
julia> params1([1.0, 2.1])
2-element Vector{params1}:
params1(1.0)
params1(2.1)
julia> params2([1.0, 2.1], 3)
2-element Vector{params2}:
params2(1.0, 3.0)
params2(2.1, 3.0)
The inner constructor for each concrete type is needed to resolve method ambiguities.