This is a classic type system straw man. The language doesn't support encoding integer ranges in the type system, ergo, the type system is not ever a significant advantage and all invariants must be documented. You fool!
What you need is to document the thing:
Some invariants require further documentation. The more you can express concisely in code via the type system, the more time you and your API clients save in both development and maintenance.
More succinctly: By expressing them in code you let the compiler automate the work of enforcing them.
Or if you're paranoid and that function can totally break your code:
An assert doesn't "protect" your code from future changes (better phrasing would be: make your code adaptable to change, loosely coupled with its dependencies as to allow iteration of your code and its dependencies independently).
An assert simply causes your code to fail in an obvious way. It's still up to you to track them down (at runtime) and figure out where you went wrong.