See https://news.ycombinator.com/item?id=49231133 An "assert" is for "impossible to fail" conditions while "throw" is for conditions which might fail within the valid state space of the program.
> Are there cases where production assertions are still necessary even when invariants are established through type constructors?
Yes. Even though there is an equivalence between "Predicates <-> Types" (Curry-Howard correspondence) many languages do not have a robust type system to avail of this (eg. C). In the "Axiomatic" approach to "Programming Language Semantics" a language construct's (eg. if/switch/while etc.) specification is given by "precondition and postcondition" which are asserts that must hold before and after the construct. This is the famous "Hoare Triple" and later extended by Dijkstra in his wp-calculus and demonstrated in his "Guarded Command Language". The same idea holds when the code between precondition and postcondition is a function/class/module/etc. in which case it is called a "Contract" for that piece of code.