That is not, in fact, a nice thing. It is exactly what you would better have different types for, that implicitly do the right thing, and only ever do the right thing.
An opaque struct confers the ability to know the set of valid operations involving said type, while not giving up any advantages of a HANDLE. Issues of indeterminate size can be worked around with a single void*/uintptr_t field.
You are not wrong; the problem is, "different types" are language-specific, whereas HANDLE is a primitive (machine-level) type that is not and thus can be easily used from any language.
HANDLE is the worst of all possible worlds.