Type inference is the ability of a compiler to work out the types of expressions on its own, without the programmer writing them down. The result is a program that is fully statically typed, and therefore checked for type errors before it runs, even though it reads almost as compactly as code in a dynamically-typed language.
The classic example comes from ML. In his 1978 paper “A Theory of Type Polymorphism in Programming,” Robin Milner presented a type discipline for polymorphic procedures together with a compile-time type-checking algorithm that enforces it. The algorithm computes types for expressions and rejects programs that cannot be consistently typed, so that an accepted program will not fail at run time on a type error.
The same idea is visible in ML’s descendants. The OCaml site explains that, thanks to type inference, programmers do not need to annotate every function parameter, return type, and variable; instead, types are inferred based on how each value is used. The compiler still catches mismatches, but the source stays uncluttered.
Type inference is a central reason languages in the ML and Haskell tradition can be both safe and concise. It removes much of the bookkeeping that earlier statically-typed languages required, while keeping the guarantees that make static typing valuable.