The case of HoldForm
appears to by design, although the motivation for that design is unclear. HoldForm
should thus be listed as one of the special heads listed in the TextString
documentation. The case of Hold
appears to be an evaluation leak, but maybe it is intentional for symmetry with HoldForm
.
HoldForm Variant
A trace of the HoldForm
variant suggests that the behaviour is by design. Here are selected evaluations from the trace:

The internal ostr
helper function has definitions that explicitly strip HoldForm
:
Needs["GeneralUtilities`"]
GeneralUtilities`TextString`PackagePrivate`ostr //
DownValues // Select[Not@*FreeQ[HoldForm]] // PrettyForm

The documentation for TextString
lists a number of heads that are treated specially -- apparently HoldForm
should be added to that list.
Hold Variant
The case of the Hold
variant is not so clear. Here is a selective trace:

There are no definitions under any of the internal helper functions that explicitly deal with Hold
. A close inspection of the trace yields use of Unevaluated
, which suggests that some attempt was made to prevent evaluation. But this measure is defeated by later steps.
My guess is that there is an evaluation leak here, but perhaps it is just a happy(?) accident that results in a treatment for Hold
that matches that of HoldForm
.
Motivation?
Why would HoldForm
be stripped when converting an expression to a string? I have no idea. It would seem that the ability to convert unevaluated expressions to strings would be valuable. If it weren't for the explicit definitions on ostr
, I would have called this a bug. Now I guess I have to call it an inscrutable design decision.
(This analysis is current as of Mathematica 11.2.0.)
DirectedInfinity
and not as an operation? $\endgroup$