The closure-appraoch is less future-proof, because you could never add another behavior to StringConsumer.
You would need to:
change the type from being a typealias to a function type to being a protocol
change all the call sites, to pass objects instead of closure
Yet adding requirements to an established protocol is also a breaking change, so I'm not sure there's too much of a difference in this regard.
The call sites could stay the same, but you would need to update all of the conforming types, or add an extension that satisfies the new protocol requirements with default implmentations
Protocols are nominally typed (if you made another protocol with a func consume(_: String) requirement, it'll be a distinct and unrelated type, despite being structurally identical) whereas closure types are structurally typed (all (String) -> Void are StringConsumer, regardless of how you spelled their type annotation)
I also have some experience with Java to compare against, which implements its lambdas as autonomous classes which conform to "functional interfaces" (interfaces with only a single requirement). I find this to usually be pretty annoying as they currently have it implemented, because there are no generalized "function types" outside of those explicitly laboriously spelled out through various functional interface declarations. But it has some benefits:
Forward compatibility: if you need to add new requirements to your interface, you could still preserve the same function signature, but just change all the lambdas into their "autonomous inner class" syntax, which lets you define an anonymous type, implement multiple constructors/methods on it, and instantiate it, all in one shot.
It lets you use lambdas where functional-interface-implementing-objects are required, because lamdas are functional-interface-implementing-objects