Sure, if you already have those values in the type parameter you can do whatever you want.
But it’s by all mean not the “only way”. In fact, it’s neither a “way” nor is it the “only” way to achieve the same effect.
It’s not a solution since you are just moving where the type instability is and it won’t help much in real code,
julia> @code_warntype Val(2)
Variables
#self#::Type{Val}
x::Int64
Body::Val{_A} where _A
1 ─ nothing
│ %2 = Core.apply_type(Base.Val, x)::Type{Val{_A}} where _A
│ %3 = (%2)()::Val{_A} where _A
└── return %3
It’s not the only way to achieve this since you can go with whatever type parameter you like,
julia> struct C{P, M}
C(::NTuple{x}, ::NTuple{y}) where {x, y} = new{x + y, x - y}()
end
julia> @code_warntype C((1, 2, 3), (2, 3))
Variables
#self#::Type{C}
#unused#@_2::Tuple{Int64,Int64,Int64}
#unused#@_3::Tuple{Int64,Int64}
Body::C{5,1}
1 ─ %1 = ($(Expr(:static_parameter, 1)) + $(Expr(:static_parameter, 2)))::Core.Compiler.Const(5, false)
│ %2 = ($(Expr(:static_parameter, 1)) - $(Expr(:static_parameter, 2)))::Core.Compiler.Const(1, false)
│ %3 = Core.apply_type(Main.C, %1, %2)::Core.Compiler.Const(C{5,1}, false)
│ %4 = %new(%3)::Core.Compiler.Const(C{5,1}(), false)
└── return %4