Type-checking (or more correctly, static type-checking) is a compile time feature provided by some programming languages.

Apart from in pure OO languages, every piece of data in a programming language has a type. In laymans' terms, the type can be viewed as telling the computer what type of data is going to be stored in a certain place (known as a variable). For instance, it could have the type integer for numbers and string for strings of text.

Static type-checking is a feature that attempts to make sure that certain rules of how to use types are followed. As a simple example, it is clearly wrong to try and put data of type string into a space meant for an integer. As an example of why this is wrong, imagine what would happen if we tried to add two strings together, thinking they were integer numbers!

Static type checking should prevent such things ever happening by throwing an error at compile time. There are disadvantages to this feature, the biggest of which is probably added language verbosity. For any given function, you have to define the return type, arguments and exception types. This makes function definitions somewhat verbose.

There are also dangers to code reuse (something C++ pretty much gets around with templates). Because any given function is so tightly defined, it can only be used for the exact task which it was defined. Imagine we have a function print() that took an argument of type integer and we want to print a string! We'd need another function.

Despite these drawbacks, many people feel that static type-checking is worth it for the plethora of runtime errors it can help avoid. However, the polar viewpoint is that the added language complexity and verbosity can lead to more errors.