The function signature for func_returnsInput
is as follows:
const func_returnsInput: (input: string) => Promise<string>
This means that it specifically takes a string
input and returns a Promise<string>
. You could tweak the implementation slightly while still adhering to this type signature:
const func_returnsInput = (input: string): Promise<string> =>
Promise.resolve(input.toUpperCase());
The compiler only focuses on the call signature, not the specific implementation. If someone provides me with func_returnsInput
, all I know is that it expects a string
input and will return a Promise<string>
. Feeding it anything other than a string
would be incorrect.
Now let's compare that to the type ReturnsInput_T
:
type ReturnsInput_T = <T>(data: T) => Promise<T>;
This is a generic function signature with a type parameter T
. The caller, not the implementer, can specify the type parameter. So, ReturnsInput_T
is a function that can accept any value chosen by the caller and will return a Promise
of the same type.
You can think of a generic call signature as an infinite intersection of all possible types for T
, even though it cannot be explicitly written out.
From this perspective, it becomes clear why you cannot assign func_returnsInput
to a variable of type ReturnsInput
:
const test: ReturnsInput_T = func_returnsInput; // error!
// Type 'T' is not assignable to type 'string'.
test(123); // no error
If test
truly has the type ReturnsInput_T
, then I should be able to call it with any type of data and get back a Promise
of the same type. However, the compiler cannot infer this behavior from func_returnsInput
.
Thus, an error occurs!
Click here to view in TypeScript Playground