CartID cartId = new CartID(productId.toString());
addToCart(..., cartId, ...); <-- but look that's really a ProductID!
I'd suggest that while you may have reduced the likelihood of certain errors you have not actually eliminated those errors.The right approach here is to be very suspicious of any methods in your domain that just take a bunch of IDs. Either:
(a) Force the caller to resolve the IDs to actual entities before invoking the method:
addToCart(Cart c, Product p, ...)
or (b) Represent the method parameters as a Parameters object or, preferrably, an Event object. handle(ProductAddedEvent event);
The real problem here is not the type system but a domain that is not sufficiently protected by an Anti-Corruption Layer [1]. Unfortunately most developers are not familiar with this kind of strategic design and languages are not much help here. It would be interesting if there was a language that could flag things like weak ACLs.[1] https://docs.microsoft.com/en-us/azure/architecture/patterns...