I'm writing a React application using TypeScript.
I've written a wrapper for a function that makes an API call:
import { ROUTE_CANDIDATES, ROUTE_TWIG_PICK } from "../../../config/constants/routes";
import { pickSchema } from "../../../config/schemas/picks";
import { PickCreateBulkResponse, PickCreateUpdateResponse } from "../../../config/types";
import { postRequest, putRequest } from "../../utils/serverRequests";
interface PickJSON {
candidate: string;
picked_int_choice: string;
}
const pickListSchema = [pickSchema];
export const postPickCreate = (
body: PickJSON | PickJSON[]
): Promise<PickCreateUpdateResponse | PickCreateBulkResponse> => {
if (Array.isArray(body)) {
return postRequest(ROUTE_CANDIDATES + ROUTE_TWIG_PICK, body, pickListSchema) as Promise<
PickCreateBulkResponse
>;
} else {
return postRequest(ROUTE_CANDIDATES + ROUTE_TWIG_PICK, body, pickSchema) as Promise<
PickCreateUpdateResponse
>;
}
};
As you can see I'm trying to dynamically assert the correct type of the response. Meaning if the function was used with an array, it should return a Promise<PickCreateBuldResponse>
, whereas if it was used with a single object, it should return Promise<PickCreateUpdateResponse>
. How can I get TypeScript to know what it returns? As you can see above I tried using as
, but this does not work.
You can declare function overloads:
export function postPickCreate(body: PickJSON): Promise<PickCreateUpdateResponse>
export function postPickCreate(body: PickJSON[]): Promise<PickCreateBulkResponse>
export function postPickCreate(body: PickJSON | PickJSON[]):
Promise<PickCreateUpdateResponse | PickCreateBulkResponse> {
if (Array.isArray(body)) {
return postRequest(ROUTE_CANDIDATES + ROUTE_TWIG_PICK, body, pickListSchema) as
Promise<PickCreateBulkResponse>;
} else {
return postRequest(ROUTE_CANDIDATES + ROUTE_TWIG_PICK, body, pickSchema) as
Promise<PickCreateUpdateResponse>;
}
}
However, since in your case you already know the type of your value at design time and TypeScript does the type checking for you, your best approach is probably to simply separate your functions. That's what you are actually doing inside the function in the if
block:
export function postPickCreate(body: PickJSON): Promise<PickCreateUpdateResponse> {
return postRequest(ROUTE_CANDIDATES + ROUTE_TWIG_PICK, body, pickSchema) as
Promise<PickCreateUpdateResponse>;
}
export function postPickCreateRange(body: PickJSON[]): Promise<PickCreateBulkResponse> {
return postRequest(ROUTE_CANDIDATES + ROUTE_TWIG_PICK, body, pickListSchema) as
Promise<PickCreateBulkResponse>;
}