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).
- 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.