It is currently rather difficult to write custom transaction types because transaction types are implemented as class constants rather than subclasses. See the PhabricatorTransactions class, for example.
We have previously had similar issues with edges and PHIDs, both which were solved by moving to subclasses rather than class constants (see D6502 and D9837).
See discussion in D14481. There's probably also some discussion on the modularization of PHID and edge types in T2715 and T5245, respectively.
- Per T10214, we should put a typecheck on transactions somewhere in the editor pipeline. You can currently apply, say, a PasteTransaction against a Task, and things get much further than they should.