Absolutely! I usually create a builder that returns itself on each method to follow the usual builder pattern and make it easier for devs coming from other languages but the consumer can always choose to use cascading instead.
I really value immutability in my code so it's obvious from the API that after instantiation an object is not meant to be changed. Take a DI container for example, after setting it up with an InjectorBuilder (with registerFactory, registorSingleton, etc) I get an Injector that I pass around and only allows gets.
To your point of not having to copy the object to instantiate it from the builder and continuing with the Injector example, I have an Injector interface (or abstract class in Dart) and an InjectorImpl (which implements Injector + the setter methods). Then from the builder, I create a private instance of InjectorImpl which I modify through the builder and then on build return it as an Injector (basically a getter). This is an option if instantiating that object is not that expansive. I do not expose InjectorImpl to the outside world.
We’re a place where coders share, stay up-to-date and grow their careers.
We strive for transparency and don't collect excess data.