redux-toolkit icon indicating copy to clipboard operation
redux-toolkit copied to clipboard

Unexpected no-floating-promises eslint error for MutationActionCreatorResult

Open Rovack opened this issue 1 year ago • 9 comments

We have the following code:

const [mutateSomething, { isLoading }] = api.useMutateSomethingMutation();

[...]

return (
  <SomeComponent
    onSomeEvent={() => {
      mutateSomething(someArg);
    }}
  />
);

Understandably, we're getting a @typescript-eslint/no-floating-promises error.

Based on this comment, we've therefore configured our eslintrc with the following:

    '@typescript-eslint/no-floating-promises': [
      'error',
      {
        allowForKnownSafePromises: [
          { from: 'package', name: 'SafePromise', package: '@reduxjs/toolkit' },
        ],
      },
    ],

However, the eslint error isn't disappearing. Are we missing something, or does this just not work for this case for some reason?

Versions

  • "@reduxjs/toolkit": "^2.2.6"
  • "@typescript-eslint/eslint-plugin": "^7.13.1"
  • "@typescript-eslint/parser": "^7.13.1"
  • "eslint-plugin-react": "^7.34.3"

Rovack avatar Jul 11 '24 22:07 Rovack

@Rovack Is this still an issue?

aryaemami59 avatar Jan 03 '25 04:01 aryaemami59

Yes, I just tried updating the dependencies and it doesn't look like anything's changed, with versions:

  • "@reduxjs/toolkit": "2.5.0"
  • "@typescript-eslint/eslint-plugin": "7.18.0"
  • "@typescript-eslint/parser": "7.18.0"
  • "eslint-plugin-react": "7.37.3"

Rovack avatar Jan 05 '25 10:01 Rovack

Maybe you also need to add the RTKQ export?

    '@typescript-eslint/no-floating-promises': [
      'error',
      {
        allowForKnownSafePromises: [
          { from: 'package', name: 'SafePromise', package: '@reduxjs/toolkit' },
+          { from: 'package', name: 'SafePromise', package: '@reduxjs/toolkit/query' },
+          { from: 'package', name: 'SafePromise', package: '@reduxjs/toolkit/query/react' },
        ],
      },
    ],

phryneas avatar Jan 05 '25 17:01 phryneas

Unfortunately it still doesn't work with the addition of those lines. Not really sure how to debug why not.

Rovack avatar Jan 07 '25 13:01 Rovack

I'm seeing this lint report on all Promises, too. Not sure if I'm setting things up wrong or what.

Minimal reproduction in https://github.com/typescript-eslint/examples/pull/20/files:

git clone https://github.com/typescript-eslint/examples
gh pr checkout 20
npm i
cd packages/redux-toolkit-floating-promises
npm run lint
.../index.ts
  16:1  error  Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the `void` operator  @typescript-eslint/no-floating-promises

I tried downgrading from the latest @reduxjs/[email protected] to all the versions since #4102 was merged, including down to 2.2.0. Still the lint report.

JoshuaKGoldberg avatar Jan 16 '25 13:01 JoshuaKGoldberg

@JoshuaKGoldberg did you also try to add the other two packages?

phryneas avatar Jan 16 '25 20:01 phryneas

Ah, I did, I just neglected to check them in. Same issue. Added in https://github.com/typescript-eslint/examples/pull/20/commits/185fa5c6d3d9dfa6bcaa876f40195a36f0e348fe.

JoshuaKGoldberg avatar Jan 17 '25 13:01 JoshuaKGoldberg

I did a bit of digging. The hover display for the type of store.dispatch(exampleThunk()) is:

Promise<PayloadAction<void, string, {
    arg: void;
    requestId: string;
    requestStatus: "fulfilled";
}, never> | PayloadAction<unknown, string, {
    arg: void;
    requestId: string;
    requestStatus: "rejected";
    aborted: boolean;
    condition: boolean;
} & ({
    ...;
} | ({
    ...;
} & {})), SerializedError>> & {
    ...;
} & {
    ...;
}

Ignoring deeper bits, that's a union of:

  • Promise< PayloadAction<...> >
  • PayloadAction<...>
  • {...}
  • {...}

...so it makes sense the rule is reporting. The value might be a Promise. Even if we added PayloadAction to the allowForKnownSafePromises list, it might be a not-known-to-be-safe type.

Is store.dispatch() supposed to return a SafePromise, rather than a Promise?

JoshuaKGoldberg avatar May 21 '25 17:05 JoshuaKGoldberg

It already does, that's the first intersection you're seeing.

https://github.com/reduxjs/redux-toolkit/blob/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/packages/toolkit/src/createAsyncThunk.ts#L239

Promise<SuccessAction | FailureAction> & SafePromiseBrand & ExtraMethods

EskiMojo14 avatar May 21 '25 17:05 EskiMojo14