The implementation technique used by Jun Furuse is to duplicate the implementation of the type-checker, and change only the parts that type-check constructor applications. This is the least-constraining way to write type-aware transformations as ppx extensions. A more concise way is to call compiler-libs for type-checking and postprocess the resulting typed AST, but this is only reasonable if the input source is expected to be well-typed.
(There are few limit on the kind of transformations you can do if you are, in fact, willing to fork the compiler codebase if necessary. But, as Jonas Jensen mentioned, this is "adventurous" indeed.)