I think what you are doing is already the best approach. The native Ecto.schema/2 macro does not require a typespec on a field and there is no practical definition that I can see that makes sense to type Money.Ecto.Composite.Type since it the function signatures for load, dump and cast can take many forms.
Very open to alternative opinions, improved docs or other suggestions.