I have a situation where I have a type which is a union of two functions which have a literal value as the type of one of their arguments. Boiled down to a minimal example, it is essentially this:
type FetchMini = (id: number, representation: 'mini') => MiniUser;
type FetchFull = (id: number, representation: 'full') => FullUser;
function f(fetchUser: FetchMini | FetchFull) {
fetchUser(2, 'mini');
fetchUser(2, 'full');
}
Both of these calls fail the compiler with the message:
Cannot invoke an expression whose type lacks a call signature. Type 'FetchMini | FetchFull' has no compatible call signatures.`
I think I understand the reason why this happens, (...I think) but what could I do about it?
Here's a similar question, however it got no answers: Union of functions is not callable even with parameters that meet each function's constraints
Your fetchUser() is essentially an overloaded function which accepts both mini and full, thus should be intersection-typed, rather than union.
type MiniUser = { name: string }
type FullUser = { firstName: string, lastName: string, age: number }
type FetchMini = (id: number, representation: 'mini') => MiniUser;
type FetchFull = (id: number, representation: 'full') => FullUser;
type FetchBoth = FetchMini&FetchFull
function f(fetchUser: FetchBoth) {
fetchUser(2, 'mini');
fetchUser(2, 'full');
}
function fetchBoth(id: number, representation: 'mini'): MiniUser
function fetchBoth(id: number, representation: 'full'): FullUser
function fetchBoth(id: number, representation: 'mini' | 'full') {
if (representation==='mini')
return { name: 'Mini' }
if (representation==='full')
return { firstName: 'Full', lastName: 'User', age: 20 }
}
f(fetchBoth)
PlayGround
As a rule of thumb, when you declare a function that accepts args of both type A and B, the function should be &-typed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With