I have a following definition of SRequest
object:
type SRequest = {
headers: string[];
get(header: string): string;
get(header: 'Set-Cookie'): string[];
}
const myReq: SRequest = {
headers: [ 'a' ],
get: (header: string | 'Set-Cookie'): string | string[] => {
if (header === 'Set-Cookie') {
return [ 'x' ];
}
return '';
}
}
But it fails to compile. I thought with overloaded function I can use union type for different arguments but I get this error:
Error:
Type '(header: string | 'Set-Cookie') => string | string[]' is not assignable to type '{ (header: string): string; (header: "Set-Cookie"): string[]; }'.
Type 'string | string[]' is not assignable to type 'string'.
Type 'string[]' is not assignable to type 'string'.
The TypeScript compiler only has limited ways of understanding function implementations. It basically just looks what the the type of each return statement is and creates a union of those types. In this case, that would result in string | string[]
which conflicts with your overloads.
It probably feels like an unsatisfying solution, but forcefully silencing the error with an assertion might be the only way.
const myReq: SRequest = {
headers: [ 'a' ],
get: (header) => {
if (header === 'Set-Cookie') {
return [ 'x' ] as string & string[]
}
return '' as string & string[]
}
}
The overload definition demands that the implementation must return a string
and a string[]
to satisfy both overloads; hence the interseciton. While not being truly type-safe, it would at least give some warnings when you would try to return a number
for example.