Is it possible to apply overloads of a TypeScript function based on the class type of the parameter?
I realize that the "classes" will be compiled down to plain functions in the output, but am hoping to get the type checking to work depending on the input type.
The goal is to create a send() function for server communication that returns a typed response based on the type of request. However, TypeScript appears to be always selecting the first overload regardless of the class type passed in.
interface IRequest {
getBody(): object;
}
class UserRequest implements IRequest {
getBody() {
return { type: 'user', id: 7 };
}
}
class CompanyRequest implements IRequest {
getBody() {
return { type: 'company', id: 42 };
}
}
interface IUserResponse {
userName: string;
}
interface ICompanyResponse {
companyName: string;
}
function send(request: UserRequest): Promise<IUserResponse>;
function send(request: CompanyRequest): Promise<ICompanyResponse>;
async function send(request: IRequest): Promise<any> {
const response = await fetch('https://example.com/service', {
body: request.getBody(),
});
return response.json();
}
async function test() {
// Works
const userResponse = await send(new UserRequest());
userResponse.userName;
// Error: [ts] Property 'companyName' does not exist on type 'IUserResponse'. [2339]
const companyResponse = await send(new CompanyRequest());
companyResponse.companyName;
}
Swapping the order of the declared overloads reverses the problem (the return type will always be CompanyRequest instead of UserRequest).
UserRequestandCompanyRequestare obviously structurally distinct