Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No floating promises check in TypeScript

I have an asynchronous function, returning a promise. Now I want TypeScript to check if I resolve the promises. If ever I missed adding await it should show a warning. How can I do that?

export const getData = async (id: number): Promise<number> => {
  return axios.get(
    `/api/human/${id}`
  );
};

// Should show error as await is missing
console.log(getData(1));

// Should just work
console.log(await getData(2));

Maybe this can not be achieved with Typescript but eslint. Then please help me out how to do that way.

If the only option is no-floating-promises from tslint, this is not helping, as it is deprecated and not used in my code base.

Update: As @son-nguyen pointed out awaiting axios and then casting a promise is redundant. So I removed the await for it.

like image 717
lony Avatar asked Jun 19 '20 05:06

lony


People also ask

What is a floating promise?

A "floating" Promise is one that is created without any code set up to handle any errors it might throw. Floating Promises can cause several issues, such as improperly sequenced operations, ignored Promise rejections, and more.


2 Answers

Here's the changes I've made in my Typescript project in order to make ESLint warn me when I forget to add await to an async call.

.eslintrc.js

module.exports = {
  ...
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ...
    project: './tsconfig.eslint.json',
  },
  rules: {
    ...
    '@typescript-eslint/no-floating-promises': ['error'],
  },
}

tsconfig.eslint.json

{
  "extends": "./tsconfig.json",
  "include": [
    ...
    ".eslintrc.js", // ESLint's config must be included
  ],
  ...
}
like image 62
Max Ivanov Avatar answered Oct 17 '22 17:10

Max Ivanov


getData clearly declared that it returns a Promise, while you return an awaited value, which is not a Promise. The await getData() call is then problematic but the type check does not fail because a static value is safe to cast as a Promise (by simple resolving to it). It works without problem, but it does not look right because as a rule when you return a Promise (which you get from the axios.get() call), you don't need to await it, which a good editor will warn you.

Removing await now makes the result of getData() truly a Promise, you can use it as usual, either passing down the chain or awaiting to get the final value. The benefit is now the compiler or linter know your intent better and can give better advice.

export const getData = async (id: number): Promise<number> => {
  return axios.get(
    `/api/human/${id}`
  );   // returns a true Promise to be awaited outside
};
like image 26
Son Nguyen Avatar answered Oct 17 '22 17:10

Son Nguyen