Abstract. We describe a type system that identifies potential type errors in dynamically typed languages like Python. The system uses a flow-sensitive static analysis on bytecodes to compute, for every variable and program point, overapproximations of the variable's present and future use types. If the future use types are not subsumed by the present types, the further program execution may raise a type error, and a narrowing assertion is inserted; if future use and present types are disjoint, it will raise a type error, and a type error assertion is inserted. We prove that the assertions are inserted in optimal locations and thus preempt type errors earlier than dynamic, soft, and gradual typing. We describe the details of our type inference and assertion insertion, and demonstrate the results of an implementation of the system with a number of examples.