Reputation: 31
I'm trying to make the response from an axios request type-safe, but am having problems making the TypeScript compiler infer the type correctly. Consider the following function which simply returns an axios request that returns the required data in a .then block and catches any error with a .catch block:
interface ServerResponse {
data: {
User_by_pk: User;
};
}
interface User {
id: string;
password: string;
}
function postRequest() {
return axios
.request<ServerResponse>({
method: 'POST',
url: 'http://example.com',
data: someData
})
.then((res) => {
return res.data.data.User_by_pk; //User type
})
.catch((error: AxiosError<ServerResponse>) => {
console.log(error.message);
return null;
});
}
I would have assumed this function would get the return type Promise<User | null>
(The data returned in the .then is of type User), but instead, it gets the return type Promise<any>
. Changing null to undefined gives the same result. I even tried explicitly stating the return type of the function, but when calling the function with for example let user = await postRequest();
the variable user gets the type User
and not User | null
as expected.
If I remove the .catch block the function's return type is correctly recognised as Promise<User>
, but once I add the .catch it instead becomes Promise<any>
instead of Promise<User | null>
.
I did some googling and some people suggested using a library with a Maybe or Result type like True Myth, but it seems a bit overkill if this functionality is already built into TypeScript with Optionals and the? operator (Optional Chaining). How can I get TypeScript to give the correct return type of my function?
Upvotes: 2
Views: 714
Reputation: 31
So, it turns out I just had an error in my tsconfig which made the file not included and thus strict checking was turned off. Once fixed, my original code gets the right type inferred! So, if anyone else has this problem make sure strict is turned on and that your file is included in the include section of your tsconfig.
To reproduce, the return type of the following function is string
when strict is turned off and "true" | null
when strict is turned on. This is obviously the behaviour you want :)
function test(input: boolean) {
if (input) return 'true';
else return undefined;
}
Upvotes: 1
Reputation: 251
Try converting the function into async
async function postRequest() {
try {
const response = await axios.request<ServerResponse>({
method: "POST",
url: "http://example.com",
data: {}
});
return response.data.data.User_by_pk;
} catch (error) {
console.log(error.message);
return null;
}
}
I gave a run to the code that you provided in a code sandbox env, and It seems to be interpreting the expected type, have a look
https://codesandbox.io/s/typescript-vi1l7?file=/src/index.ts
Upvotes: 0