diff --git a/package-lock.json b/package-lock.json index 89e42c3..3c1df0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -884,6 +884,30 @@ "dev": true, "license": "MIT" }, + "node_modules/@reduxjs/toolkit": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.5.0.tgz", + "integrity": "sha512-awNe2oTodsZ6LmRqmkFhtb/KH03hUhxOamEQy411m3Njj3BbFvoBovxo4Q1cBWnV1ErprVj9MlF0UPXkng0eyg==", + "license": "MIT", + "dependencies": { + "immer": "^10.0.3", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.41.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.0.tgz", @@ -2601,6 +2625,16 @@ "node": ">= 4" } }, + "node_modules/immer": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", + "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -3230,6 +3264,25 @@ "node": ">= 12.13.0" } }, + "node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "license": "MIT" + }, + "node_modules/redux-thunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "license": "MIT", + "peerDependencies": { + "redux": "^5.0.0" + } + }, + "node_modules/redux-toolkit-floating-promises": { + "resolved": "packages/redux-toolkit-floating-promises", + "link": true + }, "node_modules/require-from-string": { "version": "2.0.2", "license": "MIT", @@ -3237,6 +3290,12 @@ "node": ">=0.10.0" } }, + "node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", + "license": "MIT" + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -4037,6 +4096,19 @@ "typescript-eslint": "^8.32.1" } }, + "packages/redux-toolkit-floating-promises": { + "version": "0.0.0", + "license": "MIT", + "dependencies": { + "@reduxjs/toolkit": "2.5.0" + }, + "devDependencies": { + "@types/node": "^22.10.7", + "eslint": "^9.16.0", + "typescript": "^5.7.2", + "typescript-eslint": "^8.18.0" + } + }, "packages/typed-rule-via-linter": { "version": "0.0.0", "license": "MIT", diff --git a/packages/redux-toolkit-floating-promises/README.md b/packages/redux-toolkit-floating-promises/README.md new file mode 100644 index 0000000..8b89e63 --- /dev/null +++ b/packages/redux-toolkit-floating-promises/README.md @@ -0,0 +1,25 @@ +# Example: `redux-toolkit` and Floating Promise Detection + +An example of using [`redux-toolkit`](https://redux-toolkit.js.org) along with the [`@typescript-eslint/no-floating-promises` rule](https://typescript-eslint.io/rules/no-floating-promises) enabled. +It uses the [`allowForKnownSafePromises` rule option](https://typescript-eslint.io/rules/no-floating-promises/#allowforknownsafepromises) to not report on RTK APIs that create a `SafePromise`, such as `createAsyncThunk`. + +## Setup + +```shell +npm i +``` + +## Usage + +```shell +npm run lint +``` + +There should be no lint reports. + +If you remove the `allowForKnownSafePromises` option from `eslint.config.js`, there will be: + +```plaintext +.../index.test.ts + 4: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 +``` \ No newline at end of file diff --git a/packages/redux-toolkit-floating-promises/eslint.config.js b/packages/redux-toolkit-floating-promises/eslint.config.js new file mode 100644 index 0000000..b418e95 --- /dev/null +++ b/packages/redux-toolkit-floating-promises/eslint.config.js @@ -0,0 +1,29 @@ +// @ts-check + +import eslint from "@eslint/js"; +import tseslint from "typescript-eslint"; + +export default tseslint.config( + eslint.configs.recommended, + tseslint.configs.recommendedTypeChecked, + { + languageOptions: { + parserOptions: { + projectService: { + allowDefaultProject: ['*.config.*'] + }, + }, + }, + rules: { + "@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' }, + ] + } + ] + } + } +); diff --git a/packages/redux-toolkit-floating-promises/index.ts b/packages/redux-toolkit-floating-promises/index.ts new file mode 100644 index 0000000..81eba26 --- /dev/null +++ b/packages/redux-toolkit-floating-promises/index.ts @@ -0,0 +1,16 @@ +import { configureStore, createAsyncThunk } from '@reduxjs/toolkit'; + +function reducer() { + // ... +} + +const store = configureStore({ reducer }); + +const exampleThunk = createAsyncThunk( + 'example', + async () => { + // ... + }, +); + +store.dispatch(exampleThunk()); diff --git a/packages/redux-toolkit-floating-promises/package.json b/packages/redux-toolkit-floating-promises/package.json new file mode 100644 index 0000000..fc0a59d --- /dev/null +++ b/packages/redux-toolkit-floating-promises/package.json @@ -0,0 +1,26 @@ +{ + "name": "redux-toolkit-floating-promises", + "version": "0.0.0", + "description": "Example of using `redux-toolkit` with `@typescript-eslint/no-floating-promises`'s `allowForKnownSafePromises` option.", + "main": "index.ts", + "repository": { + "directory": "packages/redux-toolkit-floating-promises", + "type": "git", + "url": "https://github.com/typescript-eslint/typescript-eslint-examples" + }, + "license": "MIT", + "devDependencies": { + "@types/node": "^22.10.7", + "eslint": "^9.16.0", + "typescript": "^5.7.2", + "typescript-eslint": "^8.18.0" + }, + "dependencies": { + "@reduxjs/toolkit": "2.5.0" + }, + "scripts": { + "lint": "eslint .", + "tsc": "tsc" + }, + "type": "module" +} diff --git a/packages/redux-toolkit-floating-promises/tsconfig.json b/packages/redux-toolkit-floating-promises/tsconfig.json new file mode 100644 index 0000000..5283fbc --- /dev/null +++ b/packages/redux-toolkit-floating-promises/tsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "module": "NodeNext", + "moduleResolution": "NodeNext", + "noEmit": true, + "strict": true + }, +} pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy