When a function is called with an argument, the argument type is matched to the parameter type. This means that the argument type must be the same as, or more specific than, the parameter type.
For example:
const foo = (bar: string | number) => {
console.log(bar);
}
foo('bar');
The code above works perfectly fine because the string literal type 'bar' matches the type string | number.
Now, let's consider a different scenario involving a callback function:
const foo = (bar: (baz: string | number) => void) => {
bar('baz');
// We should also try calling the callback function with a number, like bar(42),
// to match the signature of the callback function.
}
const bar = (baz: string) => {}
foo(bar);
When the code runs, we encounter an error with the line bar('baz')
:
Argument of type '(baz: string) => void' is not assignable to parameter of type '(baz: string | number) => void'.
Types of parameters 'baz' and 'baz' are incompatible.
Type 'string | number' is not assignable to type 'string'.
Type 'number' is not assignable to type 'string'.ts(2345)
It is interesting to note that in the case of the callback function, TypeScript tries to match (baz: string) => void
(argument type) to
(baz: string | number) => void
(parameter type).
However, the parameter of the callback function is matched in the opposite direction: the type string | number
(parameter of the callback's argument) is matched to type string
(parameter of the callback's parameter).
Why does the direction of type matching in the callback function differ from the non-callback scenario?