A type tells me what it is in any version of the program that the compiler accepts.
It doesn't tell me their significance for the business logic, that's what variable names are for.
If you are making a linear collection, backed by a resizeable array, your interface is clear.
If you are making something like an I/O subsystem of an OS, in 10 years your primitives suddenly may change. For example, flash storage replaces spinning disks, and you need to schedule block erasure preferably when user programs are idle. Now you need to find all the places blocks are detached from the file structure, excluding FS journaling, and change the logic there to accommodate new scenarios, trying to reuse as much code as possible for you everyday operations. In a statically typed language I can perform exhaustive search for all such cases in no time, and make guaranteed safe refactorings to deal with that problem. No so in dynamic languages.
The change happens even faster with 3rd party networked services/libraries, because their evolution is not held back by expensive experimentation.
I'm not saying it's a bad idea, just that it's not really a core application of type systems in real-world programming practice.
You don't need too advanced of a type system to implement what you're talking about. With the caveat that doing it in Java would make the code tedious to write ;-).