For example, so that Op("X", 1) isa AbstractOperator and Op("X", 1) + Op("X", 2) isa AbstractOperator (or whatever the supertype is called, it could be Operator, OpExpr, etc.).
Alternatively, consider making all expressions runtime variants of a single type, say using algebraic data types (ADTs) as implemented in a package like Moshi.jl. That is related to the design being tested out in SymbolicArrays.jl (that package is for lazy expressions of tensors, not operators, but the design would be similar).