type fnType = ((x: number) => void) | ((x: string) => void);
const fn = (innerFn: fnType) => {
innerFn("string");
}
If I do the above, typescript says that "Argument of type 'string' is not assignable to type 'never". Why does it think innerFn wants a never?
You got two machines. One slices apples, and one peels oranges. Both machine will malfunction if you put the wrong fruit in it.
Now you make a big black box with hole for fruit input. And inside the box someone else puts either an apple slicer, or an orange peeler, you aren't told which.
Now how do you know it's safe to put in an apple, or an orange?
The answer is: you can't know it's safe.
In this analogy the machines are functions, the fruit they accept are the argument types, and the black box is the union of the two.
This is why function argument types are "contravariant" (see: https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)). This means that when combined in a union like this, the resulting argument type must satisfy both sides of the union. And since
stringandnumberhave to type level overlap, there is no type that can satisfy that.When that occurs, you get
never, which lets you know that the resulting type can never exist.It's never because, as the saying goes, you can't compare apples and oranges.