This is a syntaxic form proposal. Do not erase too much things !
# lowering wo excessive erasure
_2nt(v::Tuple{Int,Int,Int}) =
NamedTuple( (:x,:y,:z) .=> v) :: @NamedTuple{x::Int,y::Int,z::Int}
@code_warntype _2nt((1,2,3))
Body::NamedTuple{(:x, :y, :z), Tuple{Int64, Int64, Int64}} # good
1 ─ %1 = (:x, :y, :z)::Core.Const((:x, :y, :z))
│ %2 = Base.broadcasted(Main.:(=>), %1, v)::Core.PartialStruct(Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple}, Nothing, Type{Pair}, Tuple{Tuple{Symbol, Symbol, Symbol}, Tuple{Int64, Int64, Int64}}}, Any[Core.Const(Pair), Core.PartialStruct(Tuple{Tuple{Symbol, Symbol, Symbol}, Tuple{Int64, Int64, Int64}}, Any[Core.Const((:x, :y, :z)), Tuple{Int64, Int64, Int64}]), Core.Const(nothing)])
│ %3 = Base.materialize(%2)::Core.PartialStruct(Tuple{Pair{Symbol, Int64}, Pair{Symbol, Int64}, Pair{Symbol, Int64}}, Any[Core.PartialStruct(Pair{Symbol, Int64}, Any[Core.Const(:x), Int64]), Core.PartialStruct(Pair{Symbol, Int64}, Any[Core.Const(:y), Int64]), Core.PartialStruct(Pair{Symbol, Int64}, Any[Core.Const(:z), Int64])])
│ %4 = Main.NamedTuple(%3)::NamedTuple
│ %5 = (:x, :y, :z)::Core.Const((:x, :y, :z))
│ %6 = Core.apply_type(Base.Tuple, Main.Int, Main.Int, Main.Int)::Core.Const(Tuple{Int64, Int64, Int64})
│ %7 = Core.apply_type(Base.NamedTuple, %5, %6)::Core.Const(NamedTuple{(:x, :y, :z), Tuple{Int64, Int64, Int64}})
│ %8 = Core.typeassert(%4, %7)::NamedTuple{(:x, :y, :z), Tuple{Int64, Int64, Int64}}
└── return %8
some calc
# inference is out of scope from desugaring from there
nt = _2nt((1,2,3))
nt.x + nt.y
–
No comment about other point, my first remark was clear enough.