diff --git a/.eslintrc b/.eslintrc index 3f6d01cb9..cd470ca15 100644 --- a/.eslintrc +++ b/.eslintrc @@ -59,7 +59,7 @@ } }, { - "files": ["**/test/**/*.ts", "**/typescript_test/**/*.ts"], + "files": ["**/test/**/*.ts", "**/type-test/**/*.ts"], "rules": { "consistent-return": "off", "max-lines": "off", diff --git a/.github/workflows/build-and-test-types.yml b/.github/workflows/build-and-test-types.yml index 6f15ae874..b1b083894 100644 --- a/.github/workflows/build-and-test-types.yml +++ b/.github/workflows/build-and-test-types.yml @@ -1,6 +1,6 @@ name: CI -on: [push, pull_request] +on: [push, pull_request, workflow_dispatch] jobs: build: @@ -65,13 +65,15 @@ jobs: node-version: ${{ matrix.node }} cache: 'yarn' + - name: Download build artifact + uses: actions/download-artifact@v4 + with: + name: package + path: . + - name: Install deps run: yarn install - # Build with the actual TS version in the repo - - name: Pack - run: yarn build && yarn pack - - name: Install build artifact run: yarn add ./package.tgz @@ -79,17 +81,17 @@ jobs: - name: Install TypeScript ${{ matrix.ts }} run: yarn add --dev typescript@${{ matrix.ts }} - - name: 'Remove source to ensure packaged types are used' - run: rm -rf src - # Remove config line that points "reselect" to the `src` folder, # so that the typetest will use the installed version instead - - run: sed -i -e /@remap-prod-remove-line/d ./typescript_test/tsconfig.json vitest.config.mts + - name: Erase path aliases + run: sed -i -e /@remap-prod-remove-line/d tsconfig.base.json - name: Test types + env: + TEST_DIST: true run: | - ./node_modules/.bin/tsc --version - yarn test:typescript + yarn tsc --version + yarn type-tests are-the-types-wrong: name: Check package config with are-the-types-wrong @@ -104,7 +106,8 @@ jobs: - name: Checkout repo uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 + - name: Download build artifact + uses: actions/download-artifact@v4 with: name: package path: . @@ -146,6 +149,12 @@ jobs: - name: Clone RTK repo run: git clone https://github.com/reduxjs/redux-toolkit.git ./redux-toolkit + - name: Cache example deps + uses: actions/cache@v4 + with: + path: ./redux-toolkit/examples/publish-ci/${{ matrix.example }}/node_modules + key: test-published-artifact-${{ matrix.example }}-node_modules + - name: Check folder contents run: ls -l . @@ -175,17 +184,6 @@ jobs: working-directory: ./redux-toolkit/examples/publish-ci/${{ matrix.example }} run: yarn info reselect && yarn why reselect - - name: Set up JDK 17 for React Native build - if: matrix.example == 'react-native' - uses: actions/setup-java@v4 - with: - java-version: '17.x' - distribution: 'temurin' - - - name: Check MSW version - working-directory: ./redux-toolkit/examples/publish-ci/${{ matrix.example }} - run: yarn why msw - - name: Build example working-directory: ./redux-toolkit/examples/publish-ci/${{ matrix.example }} env: @@ -195,3 +193,45 @@ jobs: - name: Run test step working-directory: ./redux-toolkit/examples/publish-ci/${{ matrix.example }} run: yarn test + + test-dist: + name: Run local tests against build artifact + needs: [build] + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + node: ['20.x'] + + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Use node ${{ matrix.node }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node }} + cache: 'yarn' + + - name: Install dependencies + run: yarn install + + - name: Download build artifact + uses: actions/download-artifact@v4 + with: + name: package + path: . + + - name: Check folder contents + run: ls -lah + + - name: Install build artifact + run: yarn add ./package.tgz + + - name: Erase path aliases + run: sed -i -e /@remap-prod-remove-line/d tsconfig.base.json + + - name: Run local tests against the build artifact + env: + TEST_DIST: true + run: yarn test diff --git a/.gitignore b/.gitignore index 7a4a7e462..71f5638d9 100644 --- a/.gitignore +++ b/.gitignore @@ -6,9 +6,6 @@ dist es .vscode .idea -typescript_test/should_compile/index.js -typescript_test/should_not_compile/index.js -typescript_test/common.js flow_test/should_fail/flow-typed/index.js.flow flow_test/should_pass/flow-typed/index.js.flow reselect-builds/ @@ -34,3 +31,8 @@ website/.yarn/ docs/examples/**/*.js docs/examples/**/*.jsx + +tsconfig.vitest-temp.json + +.yalc +yalc.lock diff --git a/package.json b/package.json index ed525b1e5..69fbb7b3e 100644 --- a/package.json +++ b/package.json @@ -28,12 +28,12 @@ "lint": "eslint src test", "prepack": "yarn build", "bench": "vitest --run bench --mode production", - "test": "node --expose-gc ./node_modules/vitest/dist/cli-wrapper.js --run && vitest --run --typecheck.only", - "test:watch": "node --expose-gc ./node_modules/vitest/dist/cli-wrapper.js --watch", + "test": "node --expose-gc $(yarn bin vitest) --run --typecheck", + "test:watch": "node --expose-gc $(yarn bin vitest) --watch", "test:cov": "vitest run --coverage", "type-check": "vitest --run --typecheck.only", - "type-check:trace": "vitest --run --typecheck.only && tsc --noEmit -p typescript_test/tsconfig.json --generateTrace trace && npx @typescript/analyze-trace trace && rimraf trace", - "test:typescript": "tsc --noEmit -p typescript_test/tsconfig.json", + "type-check:trace": "vitest --run --typecheck.only && tsc --noEmit -p tsconfig.test.json --generateTrace trace && npx @typescript/analyze-trace trace && rimraf trace", + "type-tests": "tsc --noEmit -p tsconfig.test.json", "docs:start": "yarn --cwd website start", "docs:build": "yarn --cwd website build", "docs:clear": "yarn --cwd website clear", @@ -58,6 +58,7 @@ "@reduxjs/toolkit": "^2.0.1", "@testing-library/react": "^14.1.2", "@types/lodash": "^4.14.175", + "@types/node": "^22.9.0", "@types/react": "^18.2.38", "@types/react-dom": "^18.2.17", "@types/shelljs": "^0.8.11", @@ -82,10 +83,7 @@ "shelljs": "^0.8.5", "tsup": "^8.2.4", "typescript": "^5.4.2", - "vitest": "^1.6.0" - }, - "resolutions": { - "esbuild": "0.23.0" + "vitest": "^2.1.5" }, "packageManager": "yarn@4.4.1" } diff --git a/scripts/writeGitVersion.mjs b/scripts/writeGitVersion.mjs index 4a9efc9b8..7e8c33149 100644 --- a/scripts/writeGitVersion.mjs +++ b/scripts/writeGitVersion.mjs @@ -1,14 +1,10 @@ -import path from 'path' -import fs from 'fs' -import { fileURLToPath } from 'node:url' - -const __filename = fileURLToPath(import.meta.url) -const __dirname = path.dirname(__filename) +import * as fs from 'node:fs' +import * as path from 'node:path' const gitRev = process.argv[2] -const packagePath = path.join(__dirname, '../package.json') -const pkg = JSON.parse(fs.readFileSync(packagePath)) +const packagePath = path.join(import.meta.dirname, '../package.json') +const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf-8')) pkg.version = `${pkg.version}-${gitRev}` fs.writeFileSync(packagePath, JSON.stringify(pkg, null, 2)) diff --git a/test/computationComparisons.spec.tsx b/test/computationComparisons.spec.tsx index 472080f05..c64fdbc30 100644 --- a/test/computationComparisons.spec.tsx +++ b/test/computationComparisons.spec.tsx @@ -3,7 +3,7 @@ */ import * as rtl from '@testing-library/react' -import React, { useLayoutEffect, useMemo } from 'react' +import { memo, useLayoutEffect, useMemo } from 'react' import type { TypedUseSelectorHook } from 'react-redux' import { Provider, shallowEqual, useSelector } from 'react-redux' import { @@ -15,18 +15,9 @@ import { import type { OutputSelector } from 'reselect' import type { RootState, Todo } from './testUtils' -import { addTodo, setupStore, toggleCompleted } from './testUtils' +import { setupStore, toggleCompleted } from './testUtils' describe('Computations and re-rendering with React components', () => { - const selector = createSelector( - (a: number) => a, - a => a - ) - - test('passes', () => { - console.log(selector(1)) - }) - let store: ReturnType beforeEach(() => { @@ -37,37 +28,40 @@ describe('Computations and re-rendering with React components', () => { }) type SelectTodoIds = OutputSelector< - [(state: RootState) => RootState['todos']], + [(state: RootState) => Todo[]], number[], typeof lruMemoize | typeof weakMapMemoize, typeof lruMemoize | typeof weakMapMemoize > type SelectTodoById = OutputSelector< - [ - (state: RootState) => RootState['todos'], - (state: RootState, id: number) => number - ], + [(state: RootState) => Todo[], (state: RootState, id: number) => number], readonly [todo: Todo | undefined], typeof lruMemoize | typeof weakMapMemoize, typeof lruMemoize | typeof weakMapMemoize > const selectTodos = (state: RootState) => state.todos - const mapTodoIds = (todos: RootState['todos']) => todos.map(({ id }) => id) - const selectTodoId = (todos: RootState, id: number) => id - const mapTodoById = (todos: RootState['todos'], id: number) => { + const mapTodoIds = (todos: Todo[]) => todos.map(({ id }) => id) + const selectTodoId = (state: RootState, id: number) => id + const mapTodoById = (todos: Todo[], id: number) => { // Intentionally return this wrapped in an array to force a new reference each time return [todos.find(todo => todo.id === id)] as const } - const selectTodoIdsDefault = createSelector([selectTodos], mapTodoIds) - console.log(`selectTodoIdsDefault name: ${selectTodoIdsDefault.name}`) + const selectTodoIdsLru = createSelector([selectTodos], mapTodoIds, { + argsMemoize: lruMemoize, + memoize: lruMemoize + }) - const selectTodoIdsResultEquality = createSelector( + const selectTodoIdsLruResultEquality = createSelector( [selectTodos], mapTodoIds, - { memoizeOptions: { resultEqualityCheck: shallowEqual } } + { + memoizeOptions: { resultEqualityCheck: shallowEqual }, + memoize: lruMemoize, + argsMemoize: lruMemoize + } ) const selectTodoIdsWeakMap = createSelector([selectTodos], mapTodoIds, { @@ -85,16 +79,18 @@ describe('Computations and re-rendering with React components', () => { } ) - const selectTodoByIdDefault = createSelector( + const selectTodoByIdLru = createSelector( [selectTodos, selectTodoId], - mapTodoById + mapTodoById, + { memoize: lruMemoize, argsMemoize: lruMemoize } ) - const selectTodoByIdResultEquality = createSelector( + const selectTodoByIdLruResultEquality = createSelector( [selectTodos, selectTodoId], mapTodoById, { memoize: lruMemoize, + argsMemoize: lruMemoize, memoizeOptions: { resultEqualityCheck: shallowEqual, maxSize: 500 } } ) @@ -111,7 +107,7 @@ describe('Computations and re-rendering with React components', () => { let listRenders = 0 let listItemMounts = 0 - const TodoListItem = React.memo(function TodoListItem({ + const TodoListItem = memo(function TodoListItem({ id, selectTodoById }: { @@ -160,11 +156,11 @@ describe('Computations and re-rendering with React components', () => { } const testCases: [string, SelectTodoIds, SelectTodoById][] = [ - ['default', selectTodoIdsDefault, selectTodoByIdDefault], + ['lru', selectTodoIdsLru, selectTodoByIdLru], [ - 'resultEquality', - selectTodoIdsResultEquality, - selectTodoByIdResultEquality + 'lruResultEquality', + selectTodoIdsLruResultEquality, + selectTodoByIdLruResultEquality ], ['weakMap', selectTodoIdsWeakMap, selectTodoByIdWeakMap], @@ -175,7 +171,7 @@ describe('Computations and re-rendering with React components', () => { ] ] - test.each(testCases)(`%s`, async (name, selectTodoIds, selectTodoById) => { + test.each(testCases)(`%s`, (name, selectTodoIds, selectTodoById) => { selectTodoIds.resetRecomputations() selectTodoIds.resetDependencyRecomputations() selectTodoById.resetRecomputations() @@ -193,51 +189,7 @@ describe('Computations and re-rendering with React components', () => { ) - // console.log(`Recomputations after render (${name}): `) - // console.log('selectTodoIds: ') - // logSelectorRecomputations(selectTodoIds as any) - // console.log('selectTodoById: ') - // logSelectorRecomputations(selectTodoById as any) - - // console.log('Render count: ', { - // listRenders, - // listItemRenders, - // listItemMounts - // }) - expect(listItemRenders).toBe(numTodos) - - rtl.act(() => { - store.dispatch(toggleCompleted(3)) - }) - - // console.log(`\nRecomputations after toggle completed (${name}): `) - // console.log('selectTodoIds: ') - // logSelectorRecomputations(selectTodoIds as any) - // console.log('selectTodoById: ') - // logSelectorRecomputations(selectTodoById as any) - - // console.log('Render count: ', { - // listRenders, - // listItemRenders, - // listItemMounts - // }) - - rtl.act(() => { - store.dispatch(addTodo({ title: 'a', description: 'b' })) - }) - - // console.log(`\nRecomputations after added (${name}): `) - // console.log('selectTodoIds: ') - // // logSelectorRecomputations(selectTodoIds as any) - // console.log('selectTodoById: ') - // // logSelectorRecomputations(selectTodoById as any) - - // console.log('Render count: ', { - // listRenders, - // listItemRenders, - // listItemMounts - // }) }) }) diff --git a/test/examples.test.ts b/test/examples.test.ts index 52132c941..b78cc5e59 100644 --- a/test/examples.test.ts +++ b/test/examples.test.ts @@ -1,3 +1,4 @@ +import type { AnyFunction } from '@internal/types' import type { OutputSelector, Selector, @@ -39,7 +40,7 @@ test('empty array', () => { }) test('identity', () => { - const identity = any>(func: Func) => func + const identity = (func: Func) => func const createNonMemoizedSelector = createSelectorCreator({ memoize: identity, argsMemoize: identity diff --git a/test/identityFunctionCheck.test.ts b/test/identityFunctionCheck.test.ts index fa7fd225e..6a776cb80 100644 --- a/test/identityFunctionCheck.test.ts +++ b/test/identityFunctionCheck.test.ts @@ -1,5 +1,5 @@ import { createSelector, setGlobalDevModeChecks } from 'reselect' -import type { LocalTestContext, RootState } from './testUtils' +import type { RootState } from './testUtils' import { localTest } from './testUtils' describe('identityFunctionCheck', () => { diff --git a/test/lruMemoize.test.ts b/test/lruMemoize.test.ts index 6c42808eb..161f3a5a4 100644 --- a/test/lruMemoize.test.ts +++ b/test/lruMemoize.test.ts @@ -435,6 +435,7 @@ describe(lruMemoize, () => { [(state, id: number) => state[id]], state => state, { + devModeChecks: { identityFunctionCheck: 'never' }, argsMemoizeOptions: { maxSize: 10 }, memoizeOptions: { maxSize: 10 } } diff --git a/test/selectorUtils.spec.ts b/test/selectorUtils.spec.ts index 47b3508dd..39c703912 100644 --- a/test/selectorUtils.spec.ts +++ b/test/selectorUtils.spec.ts @@ -1,5 +1,5 @@ import { createSelector, lruMemoize } from 'reselect' -import type { StateA, StateAB } from 'testTypes' +import type { StateA, StateAB } from './testTypes' describe('createSelector exposed utils', () => { test('resetRecomputations', () => { diff --git a/test/setup.vitest.ts b/test/setup.ts similarity index 100% rename from test/setup.vitest.ts rename to test/setup.ts diff --git a/test/testUtils.ts b/test/testUtils.ts index 9c3c0bf0d..bda865d2b 100644 --- a/test/testUtils.ts +++ b/test/testUtils.ts @@ -1,7 +1,8 @@ +import type { AnyFunction, Simplify } from '@internal/types' import type { PayloadAction } from '@reduxjs/toolkit' import { combineReducers, configureStore, createSlice } from '@reduxjs/toolkit' import { test } from 'vitest' -import type { AnyFunction, OutputSelector, Simplify } from '../src/types' +import type { OutputSelector } from 'reselect' export interface Todo { id: number diff --git a/test/tsconfig.json b/test/tsconfig.json deleted file mode 100644 index 0d98c80c8..000000000 --- a/test/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "extends": "../tsconfig.json", - "compilerOptions": { - "allowSyntheticDefaultImports": true, - "esModuleInterop": true, - "module": "ESNext", - "moduleResolution": "Node", - "emitDeclarationOnly": false, - "strict": true, - "noEmit": true, - "target": "ESNext", - "jsx": "react", - "baseUrl": ".", - "rootDir": "../", - "skipLibCheck": true, - "noImplicitReturns": false, - "noUnusedLocals": false, - "types": ["vitest/globals"], - "paths": { - "reselect": ["../src/index.ts"], // @remap-prod-remove-line - "@internal/*": ["../src/*"] - } - }, - "include": ["**/*.ts*"] -} diff --git a/tsconfig.base.json b/tsconfig.base.json new file mode 100644 index 000000000..88ecaa6e3 --- /dev/null +++ b/tsconfig.base.json @@ -0,0 +1,33 @@ +{ + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "declaration": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": ["DOM", "ESNext"], + "module": "ESNext", + "moduleResolution": "Node", + "noErrorTruncation": true, + "noFallthroughCasesInSwitch": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "paths": { + "@internal/*": ["./src/*"], + "reselect": ["./src/index.ts"] // @remap-prod-remove-line + }, + "resolveJsonModule": true, + "rootDir": "./src", + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "target": "ESNext", + "types": ["vitest/globals", "vitest/importMeta"], + "useDefineForClassFields": true, + "useUnknownInCatchVariables": true + }, + "exclude": ["dist", "website", "docs"] +} diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 000000000..c38223c25 --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,11 @@ +{ + // For building the library. + "extends": "./tsconfig.base.json", + "compilerOptions": { + "emitDeclarationOnly": true, + "jsx": "react", + "outDir": "./dist", + "rootDir": "./src" + }, + "include": ["src"] +} diff --git a/tsconfig.json b/tsconfig.json index 2e6934359..e49b10523 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,28 +1,11 @@ { + // For general development and intellisense. + // Scans the entire source code against the current TS version + // we are using during development. + "extends": "./tsconfig.test.json", "compilerOptions": { - "strict": true, - "target": "ESNext", - "module": "ESNext", - "moduleResolution": "Node", - "esModuleInterop": true, - "skipLibCheck": true, "allowJs": true, - "jsx": "react", - "noErrorTruncation": true, - "declaration": true, - "emitDeclarationOnly": true, - "outDir": "dist", - "forceConsistentCasingInFileNames": true, - "experimentalDecorators": true, - "rootDirs": ["./src"], - "rootDir": ".", - "types": ["vitest/globals", "vitest/importMeta"], - "baseUrl": ".", - "paths": { - "reselect": ["src/index.ts"], // @remap-prod-remove-line - "@internal/*": ["src/*"] - } + "checkJs": true }, - "include": ["./src/**/*"], - "exclude": ["node_modules", "dist"] + "include": ["."] } diff --git a/tsconfig.test.json b/tsconfig.test.json new file mode 100644 index 000000000..0995aae05 --- /dev/null +++ b/tsconfig.test.json @@ -0,0 +1,9 @@ +{ + // For type tests during CI. + "extends": "./tsconfig.base.json", + "compilerOptions": { + "noEmit": true, + "rootDir": "./" + }, + "include": ["type-tests"] +} diff --git a/tsup.config.ts b/tsup.config.ts index 4831184ba..31f7e203b 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -15,6 +15,8 @@ if (process.env.NODE_ENV === 'production') { ) } +const tsconfig = 'tsconfig.build.json' satisfies Options['tsconfig'] + export default defineConfig((options): Options[] => { const commonOptions: Options = { entry: { @@ -22,6 +24,7 @@ export default defineConfig((options): Options[] => { }, sourcemap: true, target: ['esnext'], + tsconfig, clean: true, ...options } diff --git a/type-tests/argsMemoize.test-d.ts b/type-tests/argsMemoize.test-d.ts index f7531f5f2..cbf269d25 100644 --- a/type-tests/argsMemoize.test-d.ts +++ b/type-tests/argsMemoize.test-d.ts @@ -23,38 +23,44 @@ const state: RootState = { ] } -describe('memoize and argsMemoize', () => { +describe('type tests', () => { test('Override Only Memoize In createSelector', () => { const selectorDefaultSeparateInlineArgs = createSelector( (state: RootState) => state.todos, todos => todos.map(t => t.id), { memoize: lruMemoize } ) + const selectorDefaultArgsAsArray = createSelector( [(state: RootState) => state.todos], todos => todos.map(t => t.id), { memoize: lruMemoize } ) + const selectorDefaultArgsAsArrayWithMemoizeOptions = createSelector( [(state: RootState) => state.todos], todos => todos.map(t => t.id), { memoize: lruMemoize, memoizeOptions: { maxSize: 2 } } ) + const selectorDefaultSeparateInlineArgsWithMemoizeOptions = createSelector( (state: RootState) => state.todos, todos => todos.map(t => t.id), { memoize: lruMemoize, memoizeOptions: { maxSize: 2 } } ) + const selectorAutotrackSeparateInlineArgs = createSelector( (state: RootState) => state.todos, todos => todos.map(t => t.id), { memoize: autotrackMemoize } ) + const selectorAutotrackArgsAsArray = createSelector( [(state: RootState) => state.todos], todos => todos.map(t => t.id), { memoize: autotrackMemoize } ) + // @ts-expect-error When memoize is autotrackMemoize, type of memoizeOptions needs to be the same as options args in autotrackMemoize. const selectorAutotrackArgsAsArrayWithMemoizeOptions = createSelector( [(state: RootState) => state.todos], @@ -62,6 +68,7 @@ describe('memoize and argsMemoize', () => { todos => todos.map(t => t.id), { memoize: autotrackMemoize, memoizeOptions: { maxSize: 2 } } ) + const selectorAutotrackSeparateInlineArgsWithMemoizeOptions = // @ts-expect-error When memoize is autotrackMemoize, type of memoizeOptions needs to be the same as options args in autotrackMemoize. createSelector( @@ -70,16 +77,19 @@ describe('memoize and argsMemoize', () => { todos => todos.map(t => t.id), { memoize: autotrackMemoize, memoizeOptions: { maxSize: 2 } } ) + const selectorWeakMapSeparateInlineArgs = createSelector( (state: RootState) => state.todos, todos => todos.map(t => t.id), { memoize: weakMapMemoize } ) + const selectorWeakMapArgsAsArray = createSelector( [(state: RootState) => state.todos], todos => todos.map(t => t.id), { memoize: weakMapMemoize } ) + // @ts-expect-error When memoize is weakMapMemoize, type of memoizeOptions needs to be the same as options args in weakMapMemoize. const selectorWeakMapArgsAsArrayWithMemoizeOptions = createSelector( [(state: RootState) => state.todos], @@ -87,6 +97,7 @@ describe('memoize and argsMemoize', () => { todos => todos.map(t => t.id), { memoize: weakMapMemoize, memoizeOptions: { maxSize: 2 } } ) + // @ts-expect-error When memoize is weakMapMemoize, type of memoizeOptions needs to be the same as options args in weakMapMemoize. const selectorWeakMapSeparateInlineArgsWithMemoizeOptions = createSelector( (state: RootState) => state.todos, @@ -94,24 +105,31 @@ describe('memoize and argsMemoize', () => { todos => todos.map(t => t.id), { memoize: weakMapMemoize, memoizeOptions: { maxSize: 2 } } ) + const createSelectorDefault = createSelectorCreator(lruMemoize) + const createSelectorWeakMap = createSelectorCreator(weakMapMemoize) + const createSelectorAutotrack = createSelectorCreator(autotrackMemoize) + const changeMemoizeMethodSelectorDefault = createSelectorDefault( (state: RootState) => state.todos, todos => todos.map(t => t.id), { memoize: weakMapMemoize } ) + const changeMemoizeMethodSelectorWeakMap = createSelectorWeakMap( (state: RootState) => state.todos, todos => todos.map(t => t.id), { memoize: lruMemoize } ) + const changeMemoizeMethodSelectorAutotrack = createSelectorAutotrack( (state: RootState) => state.todos, todos => todos.map(t => t.id), { memoize: lruMemoize } ) + const changeMemoizeMethodSelectorDefaultWithMemoizeOptions = // @ts-expect-error When memoize is changed to weakMapMemoize or autotrackMemoize, memoizeOptions cannot be the same type as options args in lruMemoize. createSelectorDefault( @@ -120,12 +138,14 @@ describe('memoize and argsMemoize', () => { todos => todos.map(t => t.id), { memoize: weakMapMemoize, memoizeOptions: { maxSize: 2 } } ) + const changeMemoizeMethodSelectorWeakMapWithMemoizeOptions = createSelectorWeakMap( (state: RootState) => state.todos, todos => todos.map(t => t.id), { memoize: lruMemoize, memoizeOptions: { maxSize: 2 } } // When memoize is changed to lruMemoize, memoizeOptions can now be the same type as options args in lruMemoize. ) + const changeMemoizeMethodSelectorAutotrackWithMemoizeOptions = createSelectorAutotrack( (state: RootState) => state.todos, @@ -140,31 +160,37 @@ describe('memoize and argsMemoize', () => { todos => todos.map(t => t.id), { argsMemoize: lruMemoize } ) + const selectorDefaultArgsAsArray = createSelector( [(state: RootState) => state.todos], todos => todos.map(t => t.id), { argsMemoize: lruMemoize } ) + const selectorDefaultArgsAsArrayWithMemoizeOptions = createSelector( [(state: RootState) => state.todos], todos => todos.map(t => t.id), { argsMemoize: lruMemoize, argsMemoizeOptions: { maxSize: 2 } } ) + const selectorDefaultSeparateInlineArgsWithMemoizeOptions = createSelector( (state: RootState) => state.todos, todos => todos.map(t => t.id), { argsMemoize: lruMemoize, argsMemoizeOptions: { maxSize: 2 } } ) + const selectorAutotrackSeparateInlineArgs = createSelector( (state: RootState) => state.todos, todos => todos.map(t => t.id), { argsMemoize: autotrackMemoize } ) + const selectorAutotrackArgsAsArray = createSelector( [(state: RootState) => state.todos], todos => todos.map(t => t.id), { argsMemoize: autotrackMemoize } ) + // @ts-expect-error When argsMemoize is autotrackMemoize, type of argsMemoizeOptions needs to be the same as options args in autotrackMemoize. const selectorAutotrackArgsAsArrayWithMemoizeOptions = createSelector( [(state: RootState) => state.todos], @@ -175,6 +201,7 @@ describe('memoize and argsMemoize', () => { argsMemoizeOptions: { maxSize: 2 } } ) + const selectorAutotrackSeparateInlineArgsWithMemoizeOptions = // @ts-expect-error When argsMemoize is autotrackMemoize, type of argsMemoizeOptions needs to be the same as options args in autotrackMemoize. createSelector( @@ -186,16 +213,19 @@ describe('memoize and argsMemoize', () => { argsMemoizeOptions: { maxSize: 2 } } ) + const selectorWeakMapSeparateInlineArgs = createSelector( (state: RootState) => state.todos, todos => todos.map(t => t.id), { argsMemoize: weakMapMemoize } ) + const selectorWeakMapArgsAsArray = createSelector( [(state: RootState) => state.todos], todos => todos.map(t => t.id), { argsMemoize: weakMapMemoize } ) + // @ts-expect-error When argsMemoize is weakMapMemoize, type of argsMemoizeOptions needs to be the same as options args in weakMapMemoize. const selectorWeakMapArgsAsArrayWithMemoizeOptions = createSelector( [(state: RootState) => state.todos], @@ -203,6 +233,7 @@ describe('memoize and argsMemoize', () => { todos => todos.map(t => t.id), { argsMemoize: weakMapMemoize, argsMemoizeOptions: { maxSize: 2 } } ) + // @ts-expect-error When argsMemoize is weakMapMemoize, type of argsMemoizeOptions needs to be the same as options args in weakMapMemoize. const selectorWeakMapSeparateInlineArgsWithMemoizeOptions = createSelector( (state: RootState) => state.todos, @@ -210,6 +241,7 @@ describe('memoize and argsMemoize', () => { todos => todos.map(t => t.id), { argsMemoize: weakMapMemoize, argsMemoizeOptions: { maxSize: 2 } } ) + // @ts-expect-error When argsMemoize is weakMapMemoize, type of argsMemoizeOptions needs to be the same as options args in weakMapMemoize. const selectorWeakMapSeparateInlineArgsWithMemoizeOptions1 = createSelector( [ @@ -222,6 +254,7 @@ describe('memoize and argsMemoize', () => { argsMemoizeOptions: { maxSize: 2 } } ) + // @ts-expect-error When argsMemoize is weakMapMemoize, type of argsMemoizeOptions needs to be the same as options args in weakMapMemoize. const selectorWeakMapSeparateInlineArgsWithMemoizeOptions2 = createSelector( (state: RootState) => state.todos, @@ -232,7 +265,7 @@ describe('memoize and argsMemoize', () => { argsMemoize: weakMapMemoize, memoizeOptions: { equalityCheck: - // @ts-expect-error + // @ts-expect-error implicit any (a, b) => a === b, maxSize: 2 }, @@ -243,6 +276,7 @@ describe('memoize and argsMemoize', () => { const createSelectorLruMemoize = createSelectorCreator({ memoize: lruMemoize }) + const selectorWeakMapSeparateInlineArgsWithMemoizeOptions3 = // @ts-expect-error When argsMemoize is weakMapMemoize, type of argsMemoizeOptions needs to be the same as options args in weakMapMemoize. createSelectorLruMemoize( @@ -252,11 +286,10 @@ describe('memoize and argsMemoize', () => { { memoize: lruMemoize, argsMemoize: weakMapMemoize, - // memoizeOptions: [], memoizeOptions: [ { equalityCheck: - // @ts-expect-error + // @ts-expect-error implicit any (a, b) => a === b, maxSize: 2 } @@ -264,6 +297,7 @@ describe('memoize and argsMemoize', () => { argsMemoizeOptions: [{ maxSize: 2 }] } ) + const selectorWeakMapSeparateInlineArgsWithMemoizeOptions4 = createSelectorLruMemoize( // @ts-expect-error @@ -273,10 +307,11 @@ describe('memoize and argsMemoize', () => { { memoizeOptions: [{ isPromise: false }], argsMemoizeOptions: - // @ts-expect-error + // @ts-expect-error implicit any (a, b) => a === b } ) + const selectorWeakMapSeparateInlineArgsWithMemoizeOptions5 = // @ts-expect-error createSelectorLruMemoize( @@ -287,9 +322,9 @@ describe('memoize and argsMemoize', () => { argsMemoize: weakMapMemoize, memoizeOptions: [{ isPromise: false }], argsMemoizeOptions: [] - // argsMemoizeOptions: (a, b) => a === b } ) + const selectorWeakMapSeparateInlineArgsWithMemoizeOptions6 = createSelectorLruMemoize( (state: RootState) => state.todos, @@ -299,27 +334,33 @@ describe('memoize and argsMemoize', () => { memoize: weakMapMemoize, memoizeOptions: [], argsMemoizeOptions: [] - // argsMemoizeOptions: (a, b) => a === b } ) + const createSelectorDefault = createSelectorCreator(lruMemoize) + const createSelectorWeakMap = createSelectorCreator(weakMapMemoize) + const createSelectorAutotrack = createSelectorCreator(autotrackMemoize) + const changeMemoizeMethodSelectorDefault = createSelectorDefault( (state: RootState) => state.todos, todos => todos.map(t => t.id), { argsMemoize: weakMapMemoize } ) + const changeMemoizeMethodSelectorWeakMap = createSelectorWeakMap( (state: RootState) => state.todos, todos => todos.map(t => t.id), { argsMemoize: lruMemoize } ) + const changeMemoizeMethodSelectorAutotrack = createSelectorAutotrack( (state: RootState) => state.todos, todos => todos.map(t => t.id), { argsMemoize: lruMemoize } ) + const changeMemoizeMethodSelectorDefaultWithMemoizeOptions = // @ts-expect-error When argsMemoize is changed to weakMapMemoize or autotrackMemoize, argsMemoizeOptions cannot be the same type as options args in lruMemoize. createSelectorDefault( @@ -328,12 +369,14 @@ describe('memoize and argsMemoize', () => { todos => todos.map(t => t.id), { argsMemoize: weakMapMemoize, argsMemoizeOptions: { maxSize: 2 } } ) + const changeMemoizeMethodSelectorWeakMapWithMemoizeOptions = createSelectorWeakMap( (state: RootState) => state.todos, todos => todos.map(t => t.id), { argsMemoize: lruMemoize, argsMemoizeOptions: { maxSize: 2 } } // When argsMemoize is changed to lruMemoize, argsMemoizeOptions can now be the same type as options args in lruMemoize. ) + const changeMemoizeMethodSelectorAutotrackWithMemoizeOptions = createSelectorAutotrack( (state: RootState) => state.todos, @@ -346,54 +389,84 @@ describe('memoize and argsMemoize', () => { const createSelectorMicroMemoize = createSelectorCreator({ memoize: microMemoize, memoizeOptions: [{ isEqual: (a, b) => a === b }], - // memoizeOptions: { isEqual: (a, b) => a === b }, argsMemoize: microMemoize, argsMemoizeOptions: { isEqual: (a, b) => a === b } }) + const selectorMicroMemoize = createSelectorMicroMemoize( (state: RootState) => state.todos, todos => todos.map(({ id }) => id) ) - assertType(selectorMicroMemoize(state)) - // @ts-expect-error - selectorMicroMemoize() + + expectTypeOf(selectorMicroMemoize(state)).items.toBeNumber() + + expectTypeOf(selectorMicroMemoize).parameter(0).not.toBeNever() + // Checking existence of fields related to `argsMemoize` - selectorMicroMemoize.cache - selectorMicroMemoize.fn() - selectorMicroMemoize.isMemoized - selectorMicroMemoize.options - // @ts-expect-error - selectorMicroMemoize.clearCache() + + expectTypeOf(selectorMicroMemoize).toHaveProperty('cache').toBeObject() + + expectTypeOf(selectorMicroMemoize).toHaveProperty('fn').toBeFunction() + + expectTypeOf(selectorMicroMemoize) + .toHaveProperty('isMemoized') + .toEqualTypeOf(true) + + expectTypeOf(selectorMicroMemoize).toHaveProperty('options').toBeObject() + + expectTypeOf(selectorMicroMemoize).not.toHaveProperty('clearCache') + // Checking existence of fields related to `memoize` - selectorMicroMemoize.memoizedResultFunc.cache - selectorMicroMemoize.memoizedResultFunc.fn() - selectorMicroMemoize.memoizedResultFunc.isMemoized - selectorMicroMemoize.memoizedResultFunc.options - // @ts-expect-error - selectorMicroMemoize.memoizedResultFunc.clearCache() + + expectTypeOf(selectorMicroMemoize.memoizedResultFunc) + .toHaveProperty('cache') + .toBeObject() + + expectTypeOf(selectorMicroMemoize.memoizedResultFunc) + .toHaveProperty('fn') + .toBeFunction() + + expectTypeOf(selectorMicroMemoize.memoizedResultFunc) + .toHaveProperty('isMemoized') + .toEqualTypeOf(true) + + expectTypeOf(selectorMicroMemoize.memoizedResultFunc) + .toHaveProperty('options') + .toBeObject() + + expectTypeOf(selectorMicroMemoize.memoizedResultFunc).not.toHaveProperty( + 'clearCache' + ) + // Checking existence of fields related to the actual memoized selector - selectorMicroMemoize.dependencies - assertType< + + expectTypeOf(selectorMicroMemoize.dependencies).toEqualTypeOf< [ (state: RootState) => { id: number completed: boolean }[] ] - >(selectorMicroMemoize.dependencies) - assertType(selectorMicroMemoize.lastResult()) - // @ts-expect-error - selectorMicroMemoize.memoizedResultFunc() - assertType( + >() + + expectTypeOf(selectorMicroMemoize.lastResult()).items.toBeNumber() + + expectTypeOf(selectorMicroMemoize.memoizedResultFunc) + .parameter(0) + .not.toBeNever() + + expectTypeOf( selectorMicroMemoize.memoizedResultFunc([{ id: 0, completed: true }]) - ) - selectorMicroMemoize.recomputations() - selectorMicroMemoize.resetRecomputations() - // @ts-expect-error - selectorMicroMemoize.resultFunc() - assertType( + ).items.toBeNumber() + + expectTypeOf(selectorMicroMemoize.recomputations).toBeCallableWith() + expectTypeOf(selectorMicroMemoize.resetRecomputations).toBeCallableWith() + + expectTypeOf(selectorMicroMemoize.resultFunc).parameter(0).not.toBeNever() + + expectTypeOf( selectorMicroMemoize.resultFunc([{ id: 0, completed: true }]) - ) + ).items.toBeNumber() // Checking to see if types dynamically change if memoize or argsMemoize are overridden inside `createSelector`. // `microMemoize` was initially passed into `createSelectorCreator` @@ -411,52 +484,94 @@ describe('memoize and argsMemoize', () => { argsMemoizeOptions: { equalityCheck: (a, b) => a === b, maxSize: 3 } } ) - assertType(selectorMicroMemoizeOverridden(state)) - // @ts-expect-error - selectorMicroMemoizeOverridden() + + expectTypeOf(selectorMicroMemoizeOverridden(state)).items.toBeNumber() + + expectTypeOf(selectorMicroMemoizeOverridden).parameter(0).not.toBeNever() + // Checking existence of fields related to `argsMemoize` - selectorMicroMemoizeOverridden.clearCache() // Prior to override, this field did NOT exist. - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverridden.cache - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverridden.fn() - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverridden.isMemoized - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverridden.options + + // Prior to override, this field did NOT exist. + expectTypeOf(selectorMicroMemoizeOverridden) + .toHaveProperty('clearCache') + .toBeFunction() + + // Prior to override, this field DID exist. + expectTypeOf(selectorMicroMemoizeOverridden).not.toHaveProperty('cache') + + // Prior to override, this field DID exist. + expectTypeOf(selectorMicroMemoizeOverridden).not.toHaveProperty('fn') + + // Prior to override, this field DID exist. + expectTypeOf(selectorMicroMemoizeOverridden).not.toHaveProperty( + 'isMemoized' + ) + + // Prior to override, this field DID exist. + expectTypeOf(selectorMicroMemoizeOverridden).not.toHaveProperty('options') + // Checking existence of fields related to `memoize` - selectorMicroMemoizeOverridden.memoizedResultFunc.clearCache() // Prior to override, this field did NOT exist. - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverridden.memoizedResultFunc.cache - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverridden.memoizedResultFunc.fn() - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverridden.memoizedResultFunc.isMemoized - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverridden.memoizedResultFunc.options + + // Prior to override, this field did NOT exist. + expectTypeOf(selectorMicroMemoizeOverridden.memoizedResultFunc) + .toHaveProperty('clearCache') + .toBeFunction() + + // Prior to override, this field DID exist. + expectTypeOf( + selectorMicroMemoizeOverridden.memoizedResultFunc + ).not.toHaveProperty('cache') + + // Prior to override, this field DID exist. + expectTypeOf( + selectorMicroMemoizeOverridden.memoizedResultFunc + ).not.toHaveProperty('fn') + + // Prior to override, this field DID exist. + expectTypeOf( + selectorMicroMemoizeOverridden.memoizedResultFunc + ).not.toHaveProperty('isMemoized') + + // Prior to override, this field DID exist. + expectTypeOf( + selectorMicroMemoizeOverridden.memoizedResultFunc + ).not.toHaveProperty('options') + // Checking existence of fields related to the actual memoized selector - assertType< + + expectTypeOf(selectorMicroMemoizeOverridden.dependencies).toEqualTypeOf< [ (state: RootState) => { id: number completed: boolean }[] ] - >(selectorMicroMemoizeOverridden.dependencies) - assertType( + >() + + expectTypeOf( selectorMicroMemoizeOverridden.memoizedResultFunc([ { id: 0, completed: true } ]) - ) - // @ts-expect-error - selectorMicroMemoizeOverridden.memoizedResultFunc() - selectorMicroMemoizeOverridden.recomputations() - selectorMicroMemoizeOverridden.resetRecomputations() - // @ts-expect-error - selectorMicroMemoizeOverridden.resultFunc() - assertType( + ).items.toBeNumber() + + expectTypeOf( + selectorMicroMemoizeOverridden.memoizedResultFunc + ).not.toBeNever() + + expectTypeOf( + selectorMicroMemoizeOverridden.recomputations + ).toBeCallableWith() + + expectTypeOf( + selectorMicroMemoizeOverridden.resetRecomputations + ).toBeCallableWith() + + expectTypeOf(selectorMicroMemoizeOverridden.resultFunc).not.toBeNever() + + expectTypeOf( selectorMicroMemoizeOverridden.resultFunc([{ id: 0, completed: true }]) - ) + ).items.toBeNumber() + // Making sure the type behavior is consistent when args are passed in as an array. const selectorMicroMemoizeOverriddenArray = createSelectorMicroMemoize( [(state: RootState) => state.todos], @@ -468,54 +583,107 @@ describe('memoize and argsMemoize', () => { argsMemoizeOptions: { equalityCheck: (a, b) => a === b, maxSize: 3 } } ) - assertType(selectorMicroMemoizeOverriddenArray(state)) - // @ts-expect-error - selectorMicroMemoizeOverriddenArray() + + expectTypeOf(selectorMicroMemoizeOverriddenArray(state)).items.toBeNumber() + + expectTypeOf(selectorMicroMemoizeOverriddenArray) + .parameter(0) + .not.toBeNever() + // Checking existence of fields related to `argsMemoize` - selectorMicroMemoizeOverriddenArray.clearCache() // Prior to override, this field did NOT exist. - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverriddenArray.cache - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverriddenArray.fn() - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverriddenArray.isMemoized - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverriddenArray.options + + // Prior to override, this field did NOT exist. + expectTypeOf(selectorMicroMemoizeOverriddenArray) + .toHaveProperty('clearCache') + .toBeFunction() + + // Prior to override, this field DID exist. + expectTypeOf(selectorMicroMemoizeOverriddenArray).not.toHaveProperty( + 'cache' + ) + // Prior to override, this field DID exist. + expectTypeOf(selectorMicroMemoizeOverriddenArray).not.toHaveProperty('fn') + + // Prior to override, this field DID exist. + expectTypeOf(selectorMicroMemoizeOverriddenArray).not.toHaveProperty( + 'isMemoized' + ) + + // Prior to override, this field DID exist. + expectTypeOf(selectorMicroMemoizeOverriddenArray).not.toHaveProperty( + 'options' + ) + // Checking existence of fields related to `memoize` - selectorMicroMemoizeOverriddenArray.memoizedResultFunc.clearCache() // Prior to override, this field did NOT exist. - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverriddenArray.memoizedResultFunc.cache - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverriddenArray.memoizedResultFunc.fn() - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverriddenArray.memoizedResultFunc.isMemoized - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverriddenArray.memoizedResultFunc.options + + // Prior to override, this field did NOT exist. + expectTypeOf(selectorMicroMemoizeOverriddenArray.memoizedResultFunc) + .toHaveProperty('clearCache') + .toBeFunction() + + // Prior to override, this field DID exist. + expectTypeOf( + selectorMicroMemoizeOverriddenArray.memoizedResultFunc + ).not.toHaveProperty('cache') + + // Prior to override, this field DID exist. + expectTypeOf( + selectorMicroMemoizeOverriddenArray.memoizedResultFunc + ).not.toHaveProperty('fn') + + // Prior to override, this field DID exist. + expectTypeOf( + selectorMicroMemoizeOverriddenArray.memoizedResultFunc + ).not.toHaveProperty('isMemoized') + + // Prior to override, this field DID exist. + expectTypeOf( + selectorMicroMemoizeOverriddenArray.memoizedResultFunc + ).not.toHaveProperty('options') + // Checking existence of fields related to the actual memoized selector - assertType< + + expectTypeOf( + selectorMicroMemoizeOverriddenArray.dependencies + ).toEqualTypeOf< [ (state: RootState) => { id: number completed: boolean }[] ] - >(selectorMicroMemoizeOverriddenArray.dependencies) - assertType( + >() + + expectTypeOf( + selectorMicroMemoizeOverriddenArray.lastResult() + ).items.toBeNumber() + + expectTypeOf( selectorMicroMemoizeOverriddenArray.memoizedResultFunc([ { id: 0, completed: true } ]) - ) - // @ts-expect-error - selectorMicroMemoizeOverriddenArray.memoizedResultFunc() - selectorMicroMemoizeOverriddenArray.recomputations() - selectorMicroMemoizeOverriddenArray.resetRecomputations() - // @ts-expect-error - selectorMicroMemoizeOverriddenArray.resultFunc() - assertType( + ).items.toBeNumber() + + expectTypeOf( + selectorMicroMemoizeOverriddenArray.memoizedResultFunc + ).not.toBeNever() + + expectTypeOf( + selectorMicroMemoizeOverriddenArray.recomputations + ).toBeCallableWith() + + expectTypeOf( + selectorMicroMemoizeOverriddenArray.resetRecomputations + ).toBeCallableWith() + + expectTypeOf(selectorMicroMemoizeOverriddenArray.resultFunc).not.toBeNever() + + expectTypeOf( selectorMicroMemoizeOverriddenArray.resultFunc([ { id: 0, completed: true } ]) - ) + ).items.toBeNumber() + const selectorMicroMemoizeOverrideArgsMemoizeOnlyWrong = // @ts-expect-error Because `memoizeOptions` should not contain `resultEqualityCheck`. createSelectorMicroMemoize( @@ -526,7 +694,7 @@ describe('memoize and argsMemoize', () => { memoizeOptions: { isPromise: false, resultEqualityCheck: - // @ts-expect-error + // @ts-expect-error implicit any (a, b) => a === b }, argsMemoizeOptions: { resultEqualityCheck: (a, b) => a === b } @@ -542,56 +710,110 @@ describe('memoize and argsMemoize', () => { argsMemoizeOptions: { resultEqualityCheck: (a, b) => a === b } } ) - assertType(selectorMicroMemoizeOverrideArgsMemoizeOnly(state)) - // @ts-expect-error - selectorMicroMemoizeOverrideArgsMemoizeOnly() + + expectTypeOf( + selectorMicroMemoizeOverrideArgsMemoizeOnly(state) + ).items.toBeNumber() + + expectTypeOf(selectorMicroMemoizeOverrideArgsMemoizeOnly) + .parameter(0) + .not.toBeNever() + // Checking existence of fields related to `argsMemoize` - selectorMicroMemoizeOverrideArgsMemoizeOnly.clearCache() // Prior to override, this field did NOT exist. - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverrideArgsMemoizeOnly.cache - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverrideArgsMemoizeOnly.fn() - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverrideArgsMemoizeOnly.isMemoized - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverrideArgsMemoizeOnly.options + + // Prior to override, this field did NOT exist. + expectTypeOf(selectorMicroMemoizeOverrideArgsMemoizeOnly) + .toHaveProperty('clearCache') + .toBeFunction() + + // Prior to override, this field DID exist. + expectTypeOf( + selectorMicroMemoizeOverrideArgsMemoizeOnly + ).not.toHaveProperty('cache') + + // Prior to override, this field DID exist. + expectTypeOf( + selectorMicroMemoizeOverrideArgsMemoizeOnly + ).not.toHaveProperty('fn') + + // Prior to override, this field DID exist. + expectTypeOf( + selectorMicroMemoizeOverrideArgsMemoizeOnly + ).not.toHaveProperty('isMemoized') + + // Prior to override, this field DID exist. + expectTypeOf( + selectorMicroMemoizeOverrideArgsMemoizeOnly + ).not.toHaveProperty('options') // Checking existence of fields related to `memoize`, these should still be the same. - selectorMicroMemoizeOverrideArgsMemoizeOnly.memoizedResultFunc.cache - selectorMicroMemoizeOverrideArgsMemoizeOnly.memoizedResultFunc.fn() - selectorMicroMemoizeOverrideArgsMemoizeOnly.memoizedResultFunc.isMemoized - selectorMicroMemoizeOverrideArgsMemoizeOnly.memoizedResultFunc.options - // @ts-expect-error Note that since we did not override `memoize` in the options object, + + expectTypeOf(selectorMicroMemoizeOverrideArgsMemoizeOnly.memoizedResultFunc) + .toHaveProperty('cache') + .toBeObject() + + expectTypeOf(selectorMicroMemoizeOverrideArgsMemoizeOnly.memoizedResultFunc) + .toHaveProperty('fn') + .toBeFunction() + + expectTypeOf(selectorMicroMemoizeOverrideArgsMemoizeOnly.memoizedResultFunc) + .toHaveProperty('isMemoized') + .toEqualTypeOf(true) + + expectTypeOf(selectorMicroMemoizeOverrideArgsMemoizeOnly.memoizedResultFunc) + .toHaveProperty('options') + .toBeObject() + + // Note that since we did not override `memoize` in the options object, // `memoizedResultFunc.clearCache` is still an invalid field access. - selectorMicroMemoizeOverrideArgsMemoizeOnly.memoizedResultFunc.clearCache() + expectTypeOf( + selectorMicroMemoizeOverrideArgsMemoizeOnly.memoizedResultFunc + ).not.toHaveProperty('clearCache') + // Checking existence of fields related to the actual memoized selector - assertType< + + expectTypeOf( + selectorMicroMemoizeOverrideArgsMemoizeOnly.dependencies + ).toEqualTypeOf< [ (state: RootState) => { id: number completed: boolean }[] ] - >(selectorMicroMemoizeOverrideArgsMemoizeOnly.dependencies) - assertType( + >() + + expectTypeOf( selectorMicroMemoizeOverrideArgsMemoizeOnly.lastResult() - ) - assertType( + ).items.toBeNumber() + + expectTypeOf( selectorMicroMemoizeOverrideArgsMemoizeOnly.memoizedResultFunc([ { id: 0, completed: true } ]) - ) - // @ts-expect-error - selectorMicroMemoizeOverrideArgsMemoizeOnly.memoizedResultFunc() - selectorMicroMemoizeOverrideArgsMemoizeOnly.recomputations() - selectorMicroMemoizeOverrideArgsMemoizeOnly.resetRecomputations() - // @ts-expect-error - selectorMicroMemoizeOverrideArgsMemoizeOnly.resultFunc() - assertType( + ).items.toBeNumber() + + expectTypeOf( + selectorMicroMemoizeOverrideArgsMemoizeOnly.memoizedResultFunc + ).not.toBeNever() + + expectTypeOf( + selectorMicroMemoizeOverrideArgsMemoizeOnly.recomputations + ).toBeCallableWith() + + expectTypeOf( + selectorMicroMemoizeOverrideArgsMemoizeOnly.resetRecomputations + ).toBeCallableWith() + + expectTypeOf( + selectorMicroMemoizeOverrideArgsMemoizeOnly.resultFunc + ).not.toBeNever() + + expectTypeOf( selectorMicroMemoizeOverrideArgsMemoizeOnly.resultFunc([ { id: 0, completed: true } ]) - ) + ).items.toBeNumber() const selectorMicroMemoizeOverrideMemoizeOnly = createSelectorMicroMemoize( (state: RootState) => state.todos, @@ -601,56 +823,110 @@ describe('memoize and argsMemoize', () => { memoizeOptions: { resultEqualityCheck: (a, b) => a === b } } ) - assertType(selectorMicroMemoizeOverrideMemoizeOnly(state)) - // @ts-expect-error - selectorMicroMemoizeOverrideMemoizeOnly() + + expectTypeOf( + selectorMicroMemoizeOverrideMemoizeOnly(state) + ).items.toBeNumber() + + expectTypeOf(selectorMicroMemoizeOverrideMemoizeOnly) + .parameter(0) + .not.toBeNever() // Checking existence of fields related to `argsMemoize` - selectorMicroMemoizeOverrideMemoizeOnly.cache - selectorMicroMemoizeOverrideMemoizeOnly.fn - selectorMicroMemoizeOverrideMemoizeOnly.isMemoized - selectorMicroMemoizeOverrideMemoizeOnly.options - // @ts-expect-error Note that since we did not override `argsMemoize` in the options object, + + expectTypeOf(selectorMicroMemoizeOverrideMemoizeOnly) + .toHaveProperty('cache') + .toBeObject() + + expectTypeOf(selectorMicroMemoizeOverrideMemoizeOnly) + .toHaveProperty('fn') + .toBeFunction() + + expectTypeOf(selectorMicroMemoizeOverrideMemoizeOnly) + .toHaveProperty('isMemoized') + .toEqualTypeOf(true) + + expectTypeOf(selectorMicroMemoizeOverrideMemoizeOnly) + .toHaveProperty('options') + .toBeObject() + + // Note that since we did not override `argsMemoize` in the options object, // `selector.clearCache` is still an invalid field access. - selectorMicroMemoizeOverrideMemoizeOnly.clearCache() + expectTypeOf(selectorMicroMemoizeOverrideMemoizeOnly).not.toHaveProperty( + 'clearCache' + ) // Checking existence of fields related to `memoize` - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverrideMemoizeOnly.memoizedResultFunc.cache - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverrideMemoizeOnly.memoizedResultFunc.fn() - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverrideMemoizeOnly.memoizedResultFunc.isMemoized - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverrideMemoizeOnly.memoizedResultFunc.options - selectorMicroMemoizeOverrideMemoizeOnly.memoizedResultFunc.clearCache() // Prior to override, this field did NOT exist. + + // Prior to override, this field DID exist. + expectTypeOf( + selectorMicroMemoizeOverrideMemoizeOnly.memoizedResultFunc + ).not.toHaveProperty('cache') + + // Prior to override, this field DID exist. + expectTypeOf( + selectorMicroMemoizeOverrideMemoizeOnly.memoizedResultFunc + ).not.toHaveProperty('fn') + + // Prior to override, this field DID exist. + expectTypeOf( + selectorMicroMemoizeOverrideMemoizeOnly.memoizedResultFunc + ).not.toHaveProperty('isMemoized') + + // Prior to override, this field DID exist. + expectTypeOf( + selectorMicroMemoizeOverrideMemoizeOnly.memoizedResultFunc + ).not.toHaveProperty('options') + + // Prior to override, this field did NOT exist. + expectTypeOf(selectorMicroMemoizeOverrideMemoizeOnly.memoizedResultFunc) + .toHaveProperty('clearCache') + .toBeFunction() // Checking existence of fields related to the actual memoized selector - assertType< + + expectTypeOf( + selectorMicroMemoizeOverrideMemoizeOnly.dependencies + ).toEqualTypeOf< [ (state: RootState) => { id: number completed: boolean }[] ] - >(selectorMicroMemoizeOverrideMemoizeOnly.dependencies) - assertType(selectorMicroMemoizeOverrideMemoizeOnly.lastResult()) - assertType( + >() + + expectTypeOf( + selectorMicroMemoizeOverrideMemoizeOnly.lastResult() + ).items.toBeNumber() + + expectTypeOf( selectorMicroMemoizeOverrideMemoizeOnly.memoizedResultFunc([ { id: 0, completed: true } ]) - ) - // @ts-expect-error - selectorMicroMemoizeOverrideMemoizeOnly.memoizedResultFunc() - selectorMicroMemoizeOverrideMemoizeOnly.recomputations() - selectorMicroMemoizeOverrideMemoizeOnly.resetRecomputations() - // @ts-expect-error - selectorMicroMemoizeOverrideMemoizeOnly.resultFunc() - assertType( + ).items.toBeNumber() + + expectTypeOf( + selectorMicroMemoizeOverrideMemoizeOnly.memoizedResultFunc + ).not.toBeNever() + + expectTypeOf( + selectorMicroMemoizeOverrideMemoizeOnly.recomputations + ).toBeCallableWith() + + expectTypeOf( + selectorMicroMemoizeOverrideMemoizeOnly.resetRecomputations + ).toBeCallableWith() + + expectTypeOf( + selectorMicroMemoizeOverrideMemoizeOnly.resultFunc + ).not.toBeNever() + + expectTypeOf( selectorMicroMemoizeOverrideMemoizeOnly.resultFunc([ { id: 0, completed: true } ]) - ) + ).items.toBeNumber() const selectorMicroMemoizePartiallyOverridden = // @ts-expect-error Since `argsMemoize` is set to `lruMemoize`, `argsMemoizeOptions` must match the options object parameter of `lruMemoize` @@ -663,7 +939,7 @@ describe('memoize and argsMemoize', () => { argsMemoize: lruMemoize, memoizeOptions: { equalityCheck: - // @ts-expect-error + // @ts-expect-error implicit any (a, b) => a === b, maxSize: 2 }, @@ -682,7 +958,7 @@ describe('memoize and argsMemoize', () => { memoizeOptions: [ { equalityCheck: - // @ts-expect-error + // @ts-expect-error implicit any (a, b) => a === b, maxSize: 2 } @@ -693,17 +969,7 @@ describe('memoize and argsMemoize', () => { const selectorMicroMemoizePartiallyOverridden2 = createSelectorMicroMemoize( (state: RootState) => state.todos, todos => todos.map(t => t.id), - { - // memoizeOptions: [ - // { - // equalityCheck: - // // @ts-expect-error - // (a, b) => a === b, - // maxSize: 2 - // } - // ], - argsMemoizeOptions: [{ isPromise: false }] - } + { argsMemoizeOptions: [{ isPromise: false }] } ) const selectorDefaultParametric = createSelector( @@ -718,68 +984,103 @@ describe('memoize and argsMemoize', () => { memoizeOptions: [(a, b) => a === b] } ) - assertType< - { - id: number - completed: boolean - }[] - >(selectorDefaultParametric(state, 0)) - assertType< + + expectTypeOf(selectorDefaultParametric(state, 0)).toEqualTypeOf< { id: number completed: boolean }[] - >(selectorDefaultParametric(state, 1)) - // @ts-expect-error - selectorDefaultParametric(state) - // @ts-expect-error - selectorDefaultParametric(1) - // @ts-expect-error - selectorDefaultParametric(state, '') - // @ts-expect-error - selectorDefaultParametric(state, 1, 1) + >() + + expectTypeOf(selectorDefaultParametric).parameters.not.toMatchTypeOf< + [RootState] + >() + + expectTypeOf(selectorDefaultParametric).parameters.not.toMatchTypeOf< + [number] + >() + + expectTypeOf(selectorDefaultParametric).parameters.not.toMatchTypeOf< + [RootState, string] + >() + + expectTypeOf(selectorDefaultParametric).parameters.not.toMatchTypeOf< + [RootState, number, number] + >() + // Checking existence of fields related to `argsMemoize` + // Prior to override, this field did NOT exist. - selectorDefaultParametric.cache + expectTypeOf(selectorDefaultParametric).toHaveProperty('cache').toBeObject() + // Prior to override, this field did NOT exist. - selectorDefaultParametric.fn + expectTypeOf(selectorDefaultParametric).toHaveProperty('fn').toBeObject() + // Prior to override, this field did NOT exist. - selectorDefaultParametric.isMemoized + expectTypeOf(selectorDefaultParametric) + .toHaveProperty('isMemoized') + .toEqualTypeOf(true) + // Prior to override, this field did NOT exist. - selectorDefaultParametric.options - // @ts-expect-error Prior to override, this field DID exist. - selectorDefaultParametric.clearCache() + expectTypeOf(selectorDefaultParametric) + .toHaveProperty('options') + .toBeObject() + + // Prior to override, this field DID exist. + expectTypeOf(selectorDefaultParametric).not.toHaveProperty('clearCache') // Checking existence of fields related to `memoize` - // @ts-expect-error Prior to override, this field DID exist. - selectorDefaultParametric.memoizedResultFunc.clearCache() + + // Prior to override, this field DID exist. + expectTypeOf( + selectorDefaultParametric.memoizedResultFunc + ).not.toHaveProperty('clearCache') + // Prior to override, this field did NOT exist. - selectorDefaultParametric.memoizedResultFunc.clear() + expectTypeOf(selectorDefaultParametric.memoizedResultFunc) + .toHaveProperty('clear') + .toBeFunction() // Checking existence of fields related to the actual memoized selector - assertType< + + expectTypeOf(selectorDefaultParametric.dependencies).toEqualTypeOf< [ (state: RootState, id: number) => number, (state: RootState) => { id: number; completed: boolean }[] ] - >(selectorDefaultParametric.dependencies) - assertType<{ id: number; completed: boolean }[]>( - selectorDefaultParametric.lastResult() + >() + + expectTypeOf(selectorDefaultParametric.lastResult()).toEqualTypeOf< + { + id: number + completed: boolean + }[] + >() + + expectTypeOf(selectorDefaultParametric.memoizedResultFunc) + .parameter(0) + .not.toBeNever() + + expectTypeOf(selectorDefaultParametric.memoizedResultFunc).toBeCallableWith( + 0, + [{ id: 0, completed: true }] ) - assertType<{ id: number; completed: boolean }[]>( + + expectTypeOf( selectorDefaultParametric.memoizedResultFunc(0, [ { id: 0, completed: true } ]) - ) - // @ts-expect-error - selectorDefaultParametric.memoizedResultFunc() - selectorDefaultParametric.recomputations() - selectorDefaultParametric.resetRecomputations() - // @ts-expect-error - selectorDefaultParametric.resultFunc() - assertType<{ id: number; completed: boolean }[]>( - selectorDefaultParametric.resultFunc(0, [{ id: 0, completed: true }]) - ) + ).toEqualTypeOf<{ id: number; completed: boolean }[]>() + + expectTypeOf(selectorDefaultParametric.recomputations).toBeCallableWith() + + expectTypeOf( + selectorDefaultParametric.resetRecomputations + ).toBeCallableWith() + + expectTypeOf(selectorDefaultParametric.resultFunc).toBeCallableWith(0, [ + { id: 0, completed: true } + ]) }) test('memoize And argsMemoize In createSelectorCreator', () => { @@ -796,62 +1097,119 @@ describe('memoize and argsMemoize', () => { (state: RootState) => state.todos, todos => todos.map(({ id }) => id) ) - assertType( + + expectTypeOf( selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault(state) - ) - // @ts-expect-error - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault() - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.resultFunc - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.clearCache() - // @ts-expect-error - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.cache - // @ts-expect-error - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.fn - // @ts-expect-error - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.isMemoized - // @ts-expect-error - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.options + ).items.toBeNumber() + + expectTypeOf(selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault) + .parameter(0) + .not.toBeNever() + + expectTypeOf(selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault) + .toHaveProperty('resultFunc') + .toBeFunction() + + expectTypeOf(selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault) + .toHaveProperty('clearCache') + .toBeFunction() + + expectTypeOf( + selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault + ).not.toHaveProperty('cache') + + expectTypeOf( + selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault + ).not.toHaveProperty('fn') + + expectTypeOf( + selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault + ).not.toHaveProperty('isMemoized') + + expectTypeOf( + selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault + ).not.toHaveProperty('options') + // Checking existence of fields related to `memoize` - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.memoizedResultFunc - .cache - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.memoizedResultFunc.fn() - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.memoizedResultFunc - .isMemoized - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.memoizedResultFunc - .options - // @ts-expect-error - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.memoizedResultFunc.clearCache() + expectTypeOf(selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault) + .toHaveProperty('memoizedResultFunc') + .toBeFunction() + + expectTypeOf( + selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.memoizedResultFunc + ) + .toHaveProperty('cache') + .toBeObject() + + expectTypeOf( + selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.memoizedResultFunc + ) + .toHaveProperty('fn') + .toBeFunction() + + expectTypeOf( + selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.memoizedResultFunc + ) + .toHaveProperty('isMemoized') + .toEqualTypeOf(true) + + expectTypeOf( + selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.memoizedResultFunc + ) + .toHaveProperty('options') + .toBeObject() + + expectTypeOf( + selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.memoizedResultFunc + ).not.toHaveProperty('clearCache') + // Checking existence of fields related to the actual memoized selector - assertType< + + expectTypeOf( + selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.dependencies + ).toEqualTypeOf< [ (state: RootState) => { id: number completed: boolean }[] ] - >(selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.dependencies) - assertType( + >() + + expectTypeOf( selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.lastResult() + ).items.toBeNumber() + + expectTypeOf( + selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.memoizedResultFunc ) - assertType( - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.memoizedResultFunc( - [{ id: 0, completed: true }] - ) + .parameter(0) + .not.toBeNever() + + expectTypeOf( + selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.recomputations + ).toBeCallableWith() + + expectTypeOf( + selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.resetRecomputations + ).toBeCallableWith() + + expectTypeOf( + selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.resultFunc ) - // @ts-expect-error - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.memoizedResultFunc() - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.recomputations() - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.resetRecomputations() - // @ts-expect-error - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.resultFunc() - assertType( + .parameter(0) + .not.toBeNever() + + expectTypeOf( selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.resultFunc([ { id: 0, completed: true } ]) - ) + ).items.toBeNumber() + expectTypeOf( selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.memoize ).toEqualTypeOf(microMemoize) + expectTypeOf( selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.argsMemoize ).toEqualTypeOf(weakMapMemoize) @@ -873,10 +1231,16 @@ describe('memoize and argsMemoize', () => { { // @ts-expect-error memoize: microMemoize, - // @ts-expect-error - memoizeOptions: { isEqual: (a, b) => a === b }, - // @ts-expect-error - argsMemoizeOptions: { equalityCheck: (a, b) => a === b } + memoizeOptions: { + isEqual: + // @ts-expect-error implicit any + (a, b) => a === b + }, + argsMemoizeOptions: { + equalityCheck: + // @ts-expect-error implicit any + (a, b) => a === b + } }, [] // This causes the error. ) @@ -888,6 +1252,9 @@ describe('memoize and argsMemoize', () => { todos => todos.map(t => t.id), { memoize: autotrackMemoize } ) - selector.memoizedResultFunc.clearCache + + expectTypeOf(selector.memoizedResultFunc) + .toHaveProperty('clearCache') + .toBeFunction() }) }) diff --git a/type-tests/createSelector.test-d.ts b/type-tests/createSelector.test-d.ts new file mode 100644 index 000000000..ea8ceb15a --- /dev/null +++ b/type-tests/createSelector.test-d.ts @@ -0,0 +1,1244 @@ +import { configureStore, createSlice } from '@reduxjs/toolkit' +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' +import memoizeOne from 'memoize-one' +import microMemoize from 'micro-memoize' +import type { TypedUseSelectorHook } from 'react-redux' +import { useSelector } from 'react-redux' +import type { Selector } from 'reselect' +import { createSelector, createSelectorCreator, lruMemoize } from 'reselect' +import type { StateA, StateAB } from '../test/testTypes' + +// Test exporting +export const testExportBasic = createSelector( + (state: StateA) => state.a, + a => a +) + +type Component

= (props: P) => any + +declare function connect( + selector: Selector +): (component: Component

) => Component

+ +describe('type tests', () => { + test('selector', () => { + interface State { + foo: string + } + + const selector = createSelector( + (state: State) => state.foo, + foo => foo + ) + + expectTypeOf(selector.resultFunc).toBeCallableWith('test') + + expectTypeOf(selector.recomputations).toBeFunction() + + expectTypeOf(selector.resetRecomputations).toBeFunction() + + expectTypeOf(selector({ foo: 'bar' })).toBeString() + + expectTypeOf(selector).parameters.not.toHaveProperty('1') + + expectTypeOf(selector({ foo: 'bar' })).not.toBeNumber() + + // allows heterogeneous parameter type input selectors + createSelector( + (state: { foo: string }) => state.foo, + (state: { bar: number }) => state.bar, + (foo, bar) => 1 + ) + + const selectorWithUnions = createSelector( + (state: State, val: string | number) => state.foo, + (state: State, val: string | number) => val, + (foo, val) => val + ) + }) + + test('selector as combiner', () => { + interface SubState { + foo: string + } + + interface State { + bar: SubState + } + + const subSelector = createSelector( + (state: SubState) => state.foo, + foo => foo + ) + + const selector = createSelector((state: State) => state.bar, subSelector) + + expectTypeOf(selector).parameter(0).not.toMatchTypeOf({ foo: '' }) + + expectTypeOf(selector({ bar: { foo: '' } })).not.toBeNumber() + + expectTypeOf(selector({ bar: { foo: '' } })).toBeString() + }) + + test('connect', () => { + connect( + createSelector( + (state: { foo: string }) => state.foo, + foo => ({ foo }) + ) + )(props => { + expectTypeOf(props).not.toHaveProperty('bar') + + expectTypeOf(props).toHaveProperty('foo').toBeString() + }) + + const selector2 = createSelector( + (state: { foo: string }) => state.foo, + (state: { baz: number }, props: { bar: number }) => props.bar, + (foo, bar) => ({ foo, baz: bar }) + ) + + const connected = connect(selector2)(props => { + expectTypeOf(props).toHaveProperty('foo').toBeString() + + expectTypeOf(props).toHaveProperty('bar').toBeNumber() + + expectTypeOf(props).toHaveProperty('baz').toBeNumber() + + expectTypeOf(props).not.toHaveProperty('fizz') + }) + + expectTypeOf(connected).toBeCallableWith({ bar: 42 }) + + expectTypeOf(connected) + .parameter(0) + .not.toMatchTypeOf({ bar: 42, baz: 123 }) + }) + + test('invalid type in combiner', () => { + // @ts-expect-error + createSelector( + (state: { foo: string }) => state.foo, + (foo: number) => foo + ) + + createSelector( + (state: { foo: string; bar: number; baz: boolean }) => state.foo, + (state: any) => state.bar, + (state: any) => state.baz, + // @ts-expect-error + (foo: string, bar: number, baz: boolean, fizz: string) => {} + ) + + // does not allow heterogeneous parameter type + // selectors when the combinator function is typed differently + // @ts-expect-error + createSelector( + (state: { testString: string }) => state.testString, + (state: { testNumber: number }) => state.testNumber, + (state: { testBoolean: boolean }) => state.testBoolean, + (state: { testString: string }) => state.testString, + (state: { testString: string }) => state.testString, + (state: { testString: string }) => state.testString, + (state: { testString: string }) => state.testString, + (state: { testNumber: string }) => state.testNumber, + (state: { testStringArray: string[] }) => state.testStringArray, + ( + foo1: string, + foo2: number, + foo3: boolean, + foo4: string, + foo5: string, + foo6: string, + foo7: string, + foo8: number, + foo9: string[] + ) => { + return { foo1, foo2, foo3, foo4, foo5, foo6, foo7, foo8, foo9 } + } + ) + + // does not allow a large array of heterogeneous parameter type + // selectors when the combinator function is typed differently + // @ts-expect-error + createSelector( + [ + (state: { testString: string }) => state.testString, + (state: { testNumber: number }) => state.testNumber, + (state: { testBoolean: boolean }) => state.testBoolean, + (state: { testString: string }) => state.testString, + (state: { testString: string }) => state.testString, + (state: { testString: string }) => state.testString, + (state: { testString: string }) => state.testString, + (state: { testNumber: string }) => state.testNumber, + (state: { testStringArray: string[] }) => state.testStringArray + ], + ( + foo1: string, + foo2: number, + foo3: boolean, + foo4: string, + foo5: string, + foo6: string, + foo7: string, + foo8: number, + foo9: string[] + ) => { + return { foo1, foo2, foo3, foo4, foo5, foo6, foo7, foo8, foo9 } + } + ) + }) + + test('parametric selector', () => { + interface State { + foo: string + } + + interface Props { + bar: number + } + + // allows heterogeneous parameter type selectors + const selector1 = createSelector( + (state: { testString: string }) => state.testString, + (state: { testNumber: number }) => state.testNumber, + (state: { testBoolean: boolean }) => state.testBoolean, + (state: { testString: string }) => state.testString, + (state: { testString: string }) => state.testString, + (state: { testString: string }) => state.testString, + (state: { testString: string }) => state.testString, + (state: { testString: string }) => state.testString, + (state: { testStringArray: string[] }) => state.testStringArray, + ( + foo1: string, + foo2: number, + foo3: boolean, + foo4: string, + foo5: string, + foo6: string, + foo7: string, + foo8: string, + foo9: string[] + ) => { + return { foo1, foo2, foo3, foo4, foo5, foo6, foo7, foo8, foo9 } + } + ) + + expectTypeOf(selector1).toBeCallableWith({ + testString: 'a', + testNumber: 42, + testBoolean: true, + testStringArray: ['b', 'c'] + }) + + const selector = createSelector( + (state: State) => state.foo, + (state: State, props: Props) => props.bar, + (foo, bar) => ({ foo, bar }) + ) + + // @ts-expect-error + selector({ foo: 'fizz' }) + // @ts-expect-error + selector({ foo: 'fizz' }, { bar: 'baz' }) + + const ret = selector({ foo: 'fizz' }, { bar: 42 }) + + expectTypeOf(ret).toHaveProperty('foo').toBeString() + + expectTypeOf(ret).toHaveProperty('bar').toBeNumber() + + const selector2 = createSelector( + (state: State) => state.foo, + (state: State) => state.foo, + (state: State) => state.foo, + (state: State) => state.foo, + (state: State) => state.foo, + (state: State, props: Props) => props.bar, + (foo1, foo2, foo3, foo4, foo5, bar) => ({ + foo1, + foo2, + foo3, + foo4, + foo5, + bar + }) + ) + + expectTypeOf(selector2).toBeCallableWith({ foo: 'fizz' }, { bar: 42 }) + + const selector3 = createSelector( + (s: State) => s.foo, + (s: State, x: string) => x, + (s: State, y: number) => y, + (v, x) => { + return x + v + } + ) + + expectTypeOf(selector3).parameter(1).toBeNever() + + const selector4 = createSelector( + (s: State, val: number) => s.foo, + (s: State, val: string | number) => val, + (foo, val) => { + return val + } + ) + + expectTypeOf(selector4).toBeCallableWith({ foo: 'fizz' }, 42) + }) + + test('array argument', () => { + const selector = createSelector( + [ + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }, props: { bar: number }) => props.bar + ], + (foo1, foo2, bar) => ({ foo1, foo2, bar }) + ) + + const ret = selector({ foo: 'fizz' }, { bar: 42 }) + + expectTypeOf(ret).toHaveProperty('foo1').toBeString() + + expectTypeOf(ret).toHaveProperty('foo2').toBeString() + + expectTypeOf(ret).toHaveProperty('bar').toBeNumber() + + // @ts-expect-error + createSelector([(state: { foo: string }) => state.foo]) + + // @ts-expect-error + createSelector( + [ + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo + ], + (foo: string, bar: number) => {} + ) + + createSelector( + [ + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo + ], + ( + foo1: string, + foo2: string, + foo3: string, + foo4: string, + foo5: string, + foo6: string, + foo7: string, + foo8: string, + foo9: string, + foo10: string + ) => {} + ) + + // @ts-expect-error + createSelector( + [ + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo + ], + ( + foo1, + foo2, + foo3, + foo4, + foo5, + foo6, + foo7, + foo8: number, + foo9, + foo10 + ) => {} + ) + + // @ts-expect-error + createSelector( + [ + (state: { foo: string }) => state.foo, + // @ts-expect-error + state => state.foo, + // @ts-expect-error + state => state.foo, + // @ts-expect-error + state => state.foo, + // @ts-expect-error + state => state.foo, + // @ts-expect-error + state => state.foo, + // @ts-expect-error + state => state.foo, + // @ts-expect-error + state => state.foo, + 1 + ], + // We expect an error here, but the error differs between TS versions + // @ts-ignore + (foo1, foo2, foo3, foo4, foo5, foo6, foo7, foo8, foo9) => {} + ) + + const selector2 = createSelector( + [ + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo + ], + ( + foo1: string, + foo2: string, + foo3: string, + foo4: string, + foo5: string, + foo6: string, + foo7: string, + foo8: string, + foo9: string + ) => { + return { foo1, foo2, foo3, foo4, foo5, foo6, foo7, foo8, foo9 } + } + ) + + { + const ret = selector2({ foo: 'fizz' }) + + expectTypeOf(ret).toHaveProperty('foo1').toBeString() + + expectTypeOf(ret).toHaveProperty('foo2').toBeString() + + expectTypeOf(ret).toHaveProperty('foo3').toBeString() + + expectTypeOf(ret).toHaveProperty('foo4').toBeString() + + expectTypeOf(ret).toHaveProperty('foo5').toBeString() + + expectTypeOf(ret).toHaveProperty('foo6').toBeString() + + expectTypeOf(ret).toHaveProperty('foo7').toBeString() + + expectTypeOf(ret).toHaveProperty('foo8').toBeString() + + expectTypeOf(ret).toHaveProperty('foo9').toBeString() + + expectTypeOf(ret).not.toHaveProperty('foo10') + } + + expectTypeOf(selector2).parameters.not.toHaveProperty('1') + + const parametric = createSelector( + [ + (state: { foo: string }, props: { bar: number }) => props.bar, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo, + (state: { foo: string }) => state.foo + ], + ( + bar: number, + foo1: string, + foo2: string, + foo3: string, + foo4: string, + foo5: string, + foo6: string, + foo7: string, + foo8: string + ) => { + return { foo1, foo2, foo3, foo4, foo5, foo6, foo7, foo8, bar } + } + ) + + // allows a large array of heterogeneous parameter type selectors + const correctlyTypedArraySelector = createSelector( + [ + (state: { testString: string }) => state.testString, + (state: { testNumber: number }) => state.testNumber, + (state: { testBoolean: boolean }) => state.testBoolean, + (state: { testString: string }) => state.testString, + (state: { testString: string }) => state.testString, + (state: { testString: string }) => state.testString, + (state: { testString: string }) => state.testString, + (state: { testString: string }) => state.testString, + (state: { testStringArray: string[] }) => state.testStringArray + ], + ( + foo1: string, + foo2: number, + foo3: boolean, + foo4: string, + foo5: string, + foo6: string, + foo7: string, + foo8: string, + foo9: string[] + ) => { + return { foo1, foo2, foo3, foo4, foo5, foo6, foo7, foo8, foo9 } + } + ) + + // @ts-expect-error + parametric({ foo: 'fizz' }) + + { + const ret = parametric({ foo: 'fizz' }, { bar: 42 }) + + expectTypeOf(ret).toHaveProperty('foo1').toBeString() + + expectTypeOf(ret).toHaveProperty('foo2').toBeString() + + expectTypeOf(ret).toHaveProperty('foo3').toBeString() + + expectTypeOf(ret).toHaveProperty('foo4').toBeString() + + expectTypeOf(ret).toHaveProperty('foo5').toBeString() + + expectTypeOf(ret).toHaveProperty('foo6').toBeString() + + expectTypeOf(ret).toHaveProperty('foo7').toBeString() + + expectTypeOf(ret).toHaveProperty('foo8').toBeString() + + expectTypeOf(ret).toHaveProperty('bar').toBeNumber() + + expectTypeOf(ret).not.toHaveProperty('foo9') + } + }) + + test('optional arguments conflicting', () => { + interface State { + foo: string + bar: number + baz: boolean + } + + const selector = createSelector( + (state: State) => state.baz, + (state: State, arg: string) => arg, + (state: State, arg: number) => arg, + baz => { + expectTypeOf(baz).toBeBoolean() + + expectTypeOf(baz).not.toBeNumber() + } + ) + + // @ts-expect-error the selector above has inconsistent conflicting arguments so usage should error + selector({} as State) + // @ts-expect-error + selector({} as State, 'string') + // @ts-expect-error + selector({} as State, 1) + + const selector2 = createSelector( + (state: State, prefix: any) => prefix + state.foo, + str => str + ) + + // @ts-expect-error here we require one argument which can be anything so error if there are no arguments + selector2({} as State) + // no error passing anything in + selector2({} as State, 'blach') + selector2({} as State, 1) + + // here the argument is optional so it should be possible to omit the argument or pass anything + const selector3 = createSelector( + (state: State, prefix?: any) => prefix + state.foo, + str => str + ) + + selector3({} as State) + selector3({} as State, 1) + selector3({} as State, 'blach') + + // https://github.com/reduxjs/reselect/issues/563 + const selector4 = createSelector( + (state: State, prefix: string, suffix: any) => + prefix + state.foo + String(suffix), + str => str + ) + + // @ts-expect-error + selector4({} as State) + // @ts-expect-error + selector4({} as State, 'blach') + + expectTypeOf(selector4).toBeCallableWith({} as State, 'blach', 4) + + // as above but a unknown 2nd argument + const selector5 = createSelector( + (state: State, prefix: string, suffix: unknown) => + prefix + state.foo + String(suffix), + str => str + ) + + // @ts-expect-error + selector5({} as State) + // @ts-expect-error + selector5({} as State, 'blach') + + expectTypeOf(selector5).toBeCallableWith({} as State, 'blach', 4) + + // this is an example fixing selector6. We have to add a un-necessary typing in and magically the types are correct + const selector7 = createSelector( + (state: State, prefix: string = 'a') => prefix + state.foo, + (str: string) => str + ) + + expectTypeOf(selector7).toBeCallableWith({} as State) + + expectTypeOf(selector7).toBeCallableWith({} as State, 'blach') + + // @ts-expect-error wrong type + selector7({} as State, 1) + + const selector8 = createSelector( + (state: State, prefix: unknown) => prefix, + str => str + ) + + // @ts-expect-error needs a argument + selector8({} as State) + + // allowed to pass anything as the type is unknown + expectTypeOf(selector8).toBeCallableWith({} as State, 'blach') + + expectTypeOf(selector8).toBeCallableWith({} as State, 2) + }) + + test('dynamic array argument', () => { + interface Elem { + val1: string + val2: string + } + const data: ReadonlyArray = [ + { val1: 'a', val2: 'aa' }, + { val1: 'b', val2: 'bb' } + ] + + createSelector( + data.map(obj => () => obj.val1), + (...vals) => vals.join(',') + ) + + createSelector( + data.map(obj => () => obj.val1), + // @ts-expect-error + vals => vals.join(',') + ) + + createSelector( + data.map(obj => () => obj.val1), + (...vals: string[]) => 0 + ) + // @ts-expect-error + createSelector( + data.map(obj => () => obj.val1), + (...vals: number[]) => 0 + ) + + const s = createSelector( + data.map(obj => (state: StateA, fld: keyof Elem) => obj[fld]), + (...vals) => vals.join(',') + ) + s({ a: 42 }, 'val1') + s({ a: 42 }, 'val2') + // @ts-expect-error + s({ a: 42 }, 'val3') + }) + + test('issue #445: Typescript validation issues when passing function to combiner', () => { + // https://github.com/reduxjs/reselect/issues/445 + + interface TestState { + someNumber: number | null + someString: string | null + } + + interface Object1 { + str: string + } + interface Object2 { + num: number + } + + const getNumber = (state: TestState) => state.someNumber + const getString = (state: TestState) => state.someString + + function generateObject1(str: string): Object1 { + return { + str + } + } + function generateObject2(num: number): Object2 { + return { + num + } + } + function generateComplexObject( + num: number, + subObject: Object1, + subObject2: Object2 + ): boolean { + return true + } + + // ################ Tests ################ + + // Compact selector examples + + // Should error because generateObject1 can't take null + // @ts-expect-error + const getObject1 = createSelector([getString], generateObject1) + + // Should error because generateObject2 can't take null + // @ts-expect-error + const getObject2 = createSelector([getNumber], generateObject2) + + // Should error because mismatch of params + // @ts-expect-error + const getComplexObjectTest1 = createSelector( + [getObject1], + generateComplexObject + ) + + // Does error, but error is really weird and talks about "Object1 is not assignable to type number" + // @ts-expect-error + const getComplexObjectTest2 = createSelector( + [getNumber, getObject1], + generateComplexObject + ) + + // Should error because number can't be null + // @ts-expect-error + const getComplexObjectTest3 = createSelector( + [getNumber, getObject1, getObject2], + generateComplexObject + ) + + // Does error, but error is really weird and talks about "Object1 is not assignable to type number" + // @ts-expect-error + const getComplexObjectTest4 = createSelector( + [getObject1, getNumber, getObject2], + generateComplexObject + ) + + // Verbose selector examples + + // Errors correctly, says str can't be null + const getVerboseObject1 = createSelector([getString], str => + // @ts-expect-error + generateObject1(str) + ) + + // Errors correctly, says num can't be null + const getVerboseObject2 = createSelector([getNumber], num => + // @ts-expect-error + generateObject2(num) + ) + + // Errors correctly + const getVerboseComplexObjectTest1 = createSelector([getObject1], obj1 => + // @ts-expect-error + generateComplexObject(obj1) + ) + + // Errors correctly + const getVerboseComplexObjectTest2 = createSelector( + [getNumber, getObject1], + // @ts-expect-error + (num, obj1) => generateComplexObject(num, obj1) + ) + + // Errors correctly + const getVerboseComplexObjectTest3 = createSelector( + [getNumber, getObject1, getObject2], + // @ts-expect-error + (num, obj1, obj2) => generateComplexObject(num, obj1, obj2) + ) + + // Errors correctly + const getVerboseComplexObjectTest4 = createSelector( + [getObject1, getNumber, getObject2], + // @ts-expect-error + (num, obj1, obj2) => generateComplexObject(num, obj1, obj2) + ) + }) + + test('issue #492: Props argument types not merged correctly with overlapping keys', () => { + // https://github.com/reduxjs/reselect/issues/492 + + const fooPropSelector = (_: {}, ownProps: { foo: string }) => ownProps.foo + const fooBarPropsSelector = ( + _: {}, + ownProps: { foo: string; bar: string } + ) => [ownProps.foo, ownProps.bar] + + const combinedSelector = createSelector( + fooPropSelector, + fooBarPropsSelector, + (foo, fooBar) => fooBar + ) + }) + + test('ensure that input selectors with mismatched states raise errors', () => { + const input1 = (state: string) => 1 + const input2 = (state: number) => 2 + + const selector = createSelector(input1, input2, (...args) => 0) + // @ts-expect-error + selector('foo') + // @ts-expect-error + selector(5) + + const selector1 = createSelector( + (state: { foo: string }) => 1, + (state: { bar: string }) => 2, + (...args) => 0 + ) + selector1({ foo: '', bar: '' }) + // @ts-expect-error + selector1({ foo: '' }) + // @ts-expect-error + selector1({ bar: '' }) + + const selector2 = createSelector( + (state: { foo: string }) => 1, + (state: { foo: string }) => 2, + (...args) => 0 + ) + // @ts-expect-error + selector2({ foo: '', bar: '' }) + selector2({ foo: '' }) + // @ts-expect-error + selector2({ bar: '' }) + }) + + test('issue #526: input selector with undefined return', () => { + // https://github.com/reduxjs/reselect/issues/526 + + interface Input { + field: number | undefined + } + + type Output = string + + type SelectorType = (input: Input) => Output + + const input = ({ field }: Input) => field + + const result = (out: number | undefined): Output => 'test' + + // Make sure the selector type is honored + const selector: SelectorType = createSelector( + ({ field }: Input) => field, + args => 'test' + ) + + // even when memoizeOptions are passed + const selector2: SelectorType = createSelector( + ({ field }: Input) => field, + args => 'test', + { + memoize: lruMemoize, + memoizeOptions: { maxSize: 42 } + } + ) + + // Make sure inference of functions works... + const selector3: SelectorType = createSelector(input, result) + const selector4: SelectorType = createSelector(input, result, { + memoize: lruMemoize, + memoizeOptions: { maxSize: 42 } + }) + }) + + test('issue #540: Multiple selectors with arguments result in a union type', () => { + // https://github.com/reduxjs/reselect/issues/540 + + const input1 = ( + _: StateA, + { testNumber }: { testNumber: number }, + c: number, + d: string + ) => testNumber + + const input2 = ( + _: StateA, + { testString }: { testString: string }, + c: number | string + ) => testString + + const input3 = ( + _: StateA, + { testBoolean }: { testBoolean: boolean }, + c: number | string, + d: string + ) => testBoolean + + const input4 = (_: StateA, { testString2 }: { testString2: string }) => + testString2 + + const testSelector = createSelector( + input1, + input2, + input3, + input4, + (testNumber, testString, testBoolean) => testNumber + testString + ) + + const state: StateA = { a: 42 } + const test = testSelector( + state, + { + testNumber: 1, + testString: '10', + testBoolean: true, + testString2: 'blah' + }, + 42, + 'blah' + ) + + // #541 + const selectProp1 = createSelector( + [ + (state: StateA) => state, + (state: StateA, props: { prop1: number }) => props + ], + (state, { prop1 }) => [state, prop1] + ) + + const selectProp2 = createSelector( + [selectProp1, (state, props: { prop2: number }) => props], + (state, { prop2 }) => [state, prop2] + ) + + selectProp1({ a: 42 }, { prop1: 1 }) + // @ts-expect-error + selectProp2({ a: 42 }, { prop2: 2 }) + }) + + test('issue #550: createSelector accepts selectors with more than one parameter', () => { + // https://github.com/reduxjs/reselect/issues/550 + + const some = createSelector( + (a: number) => a, + (_a: number, b: number) => b, + (a, b) => a + b + ) + + const test = some(1, 2) + }) + + test('RTK issue #1750: Type conflicts with TypedUseSelectorHook', () => { + // https://github.com/reduxjs/redux-toolkit/issues/1750 + + const slice = createSlice({ + name: 'test', + initialState: 0, + reducers: {} + }) + + interface Pokemon { + name: string + } + + // Define a service using a base URL and expected endpoints + const pokemonApi = createApi({ + reducerPath: 'pokemonApi', + baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }), + endpoints: builder => ({ + getPokemonByName: builder.query({ + query: name => `pokemon/${name}` + }) + }) + }) + + const store = configureStore({ + reducer: { + test: slice.reducer, + [pokemonApi.reducerPath]: pokemonApi.reducer + }, + middleware: getDefaultMiddleware => + getDefaultMiddleware().concat(pokemonApi.middleware) + }) + + type RootState = ReturnType + + const selectTest = createSelector( + (state: RootState) => state.test, + test => test + ) + + const useAppSelector: TypedUseSelectorHook = useSelector + + // Selector usage should compile correctly + const testItem = selectTest(store.getState()) + + function App() { + const test = useAppSelector(selectTest) + return null + } + }) + + test('handle nested incompatible types', () => { + // Incompatible parameters should force errors even for nested fields. + // One-level-deep fields get stripped to empty objects, so they + // should be replaced with `never`. + // Deeper fields should get caught by TS. + // Playground: https://tsplay.dev/wg6X0W + const input1a = (_: StateA, param: { b: number }) => param.b + + const input1b = (_: StateA, param: { b: string }) => param.b + + const testSelector1 = createSelector(input1a, input1b, () => ({})) + + // @ts-expect-error + testSelector1({ a: 42 }, { b: 99 }) // should not compile + + const input2a = (_: StateA, param: { b: { c: number } }) => param.b.c + const input2b = (_: StateA, param: { b: { c: string } }) => param.b.c + + const testSelector2 = createSelector(input2a, input2b, (c1, c2) => {}) + + // @ts-expect-error + testSelector2({ a: 42 }, { b: { c: 99 } }) + }) + + test('issue #554a: createSelector should support undefined and optional parameters', () => { + // https://github.com/reduxjs/reselect/issues/554 + + interface State { + foo: string + bar: number + } + + const initialState: State = { + foo: 'This is Foo', + bar: 1 + } + + const getFoo = (state: State) => { + return state.foo + } + getFoo(initialState) + + const getBar = (state: State) => { + return state.bar + } + getBar(initialState) + + const simple = createSelector(getFoo, getBar, (foo, bar) => { + return `${foo} => ${bar}` + }) + simple(initialState) + + // Input selectors with positional args + const firstInput = (_: State, first: string) => first + // Skip the first arg and return only the second. + const secondInput = (_: State, _first: string, second: number) => second + + const complexOne = createSelector( + getFoo, + getBar, + firstInput, + (foo, bar, first) => { + return `${foo} => ${bar} || ${first}` + } + ) + complexOne(initialState, 'first') + + const complexTwo = createSelector( + getFoo, + getBar, + firstInput, + secondInput, + (foo, bar, first, second) => { + return `${foo} => ${bar} || ${first} and ${second}` + } + ) + // TS should complain since 'second' should be `number` + // @ts-expect-error + complexTwo(initialState, 'first', 'second') + }) + + test('issue #554b: createSelector should support undefined and optional parameters', () => { + // https://github.com/reduxjs/reselect/issues/554 + + interface State { + counter1: number + counter2: number + } + + const selectTest = createSelector( + (state: State, numberA?: number) => numberA, + (state: State) => state.counter2, + (numberA, counter2) => (numberA ? numberA + counter2 : counter2) + ) + + type selectTestParams = Parameters + const p1: selectTestParams = [{ counter1: 1, counter2: 2 }, 42] + + expectTypeOf(p1).toEqualTypeOf<[State, number?]>() + + const result = selectTest({ counter1: 1, counter2: 2 }, 42) + }) + + test('issue #554c: createSelector should support undefined and optional parameters', () => { + // https://github.com/reduxjs/reselect/issues/554 + + interface State { + counter1: number + counter2: number + } + + const selectTest = createSelector( + (state: State, numberA?: number) => numberA, // `numberA` is optional + (state: State) => state.counter2, + (numberA, counter2) => (numberA ? numberA + counter2 : counter2) + ) + + // @ts-expect-error + const value = selectTest({ counter1: 0, counter2: 0 }, 'what?') + + const selectTest2 = createSelector( + (state: State, numberA: number) => numberA, // `numberA` is not optional anymore + (state: State) => state.counter2, + (numberA, counter2) => (numberA ? numberA + counter2 : counter2) + ) + + // @ts-expect-error + const value2 = selectTest2({ counter1: 0, counter2: 0 }, 'what?') + }) + + test('issue #555: createSelector should support undefined, null and optional parameters', () => { + // https://github.com/reduxjs/reselect/issues/555 + + interface IReduxState { + ui: { + x: string + y: string + } + } + + const someSelector1 = createSelector( + (state: IReduxState, param: 'x' | 'y' | undefined) => + param !== undefined ? state.ui[param] : null, + (a: string | null) => a + ) + + const someSelector2 = createSelector( + (state: IReduxState, param?: 'x' | 'y') => + param !== undefined ? state.ui[param] : null, + (a: string | null) => a + ) + + const someSelector3 = createSelector( + (state: IReduxState, param: 'x' | 'y' | null) => + param !== null ? state.ui[param] : null, + (a: string | null) => a + ) + + const state = { ui: { x: '1', y: '2' } } + + const selectorResult1 = someSelector1(state, undefined) + const selectorResult2 = someSelector2(state, undefined) + const selectorResult3 = someSelector3(state, null) + }) + + test('config options', () => { + const lruMemoizeAcceptsFirstArgDirectly = createSelector( + (state: StateAB) => state.a, + (state: StateAB) => state.b, + (a, b) => a + b, + { + memoize: lruMemoize, + memoizeOptions: (a, b) => a === b + } + ) + + const lruMemoizeAcceptsFirstArgAsObject = createSelector( + (state: StateAB) => state.a, + (state: StateAB) => state.b, + (a, b) => a + b, + { + memoize: lruMemoize, + memoizeOptions: { + equalityCheck: (a, b) => a === b + } + } + ) + + const lruMemoizeAcceptsArgsAsArray = createSelector( + (state: StateAB) => state.a, + (state: StateAB) => state.b, + (a, b) => a + b, + { + memoize: lruMemoize, + memoizeOptions: [(a, b) => a === b] + } + ) + + const customSelectorCreatorMicroMemoize = createSelectorCreator( + microMemoize, + { + maxSize: 42 + } + ) + + customSelectorCreatorMicroMemoize( + (state: StateAB) => state.a, + (state: StateAB) => state.b, + (a, b) => a + b, + { + memoizeOptions: [ + { + maxSize: 42 + } + ] + } + ) + + const customSelectorCreatorMemoizeOne = createSelectorCreator(memoizeOne) + + customSelectorCreatorMemoizeOne( + (state: StateAB) => state.a, + (state: StateAB) => state.b, + (a, b) => a + b, + { + memoizeOptions: (a, b) => a === b + } + ) + }) +}) diff --git a/type-tests/createSelector.withTypes.test-d.ts b/type-tests/createSelector.withTypes.test-d.ts index c3e00618e..6840e3d3b 100644 --- a/type-tests/createSelector.withTypes.test-d.ts +++ b/type-tests/createSelector.withTypes.test-d.ts @@ -27,7 +27,7 @@ const rootState: RootState = { ] } -describe('createSelector.withTypes()', () => { +describe('type tests', () => { const createAppSelector = createSelector.withTypes() describe('when input selectors are provided as a single array', () => { @@ -41,13 +41,13 @@ describe('createSelector.withTypes()', () => { createAppSelector( [ state => { - expectTypeOf(state).toEqualTypeOf(rootState) + expectTypeOf(state).toEqualTypeOf(rootState) return state.todos } ], todos => { - expectTypeOf(todos).toEqualTypeOf(rootState.todos) + expectTypeOf(todos).toEqualTypeOf() return todos.map(({ id }) => id) } @@ -60,21 +60,22 @@ describe('createSelector.withTypes()', () => { // Type of state is locked but the parameter types of the // result function are NOT correctly inferred when // input selectors are provided as separate inline arguments. + // NOTE: In TypeScript versions prior to 5.1, `withTypes` works correctly + // only when input selectors are provided as a single array. createAppSelector( - state => { - expectTypeOf(state).toEqualTypeOf(rootState) + [ + state => { + expectTypeOf(state).toEqualTypeOf(rootState) - return state.todos - }, + return state.todos + } + ], todos => { // Known limitation: Parameter types are not inferred in this scenario - expectTypeOf(todos).toBeAny() + expectTypeOf(todos).not.toBeAny() - expectTypeOf(todos).not.toEqualTypeOf(rootState.todos) + expectTypeOf(todos).toEqualTypeOf() - // @ts-expect-error A typed `createSelector` currently only infers - // the parameter types of the result function when - // input selectors are provided as a single array. return todos.map(({ id }) => id) } ) @@ -84,34 +85,32 @@ describe('createSelector.withTypes()', () => { // Checking to see if the type of state is correct when multiple // input selectors are provided as separate inline arguments. createAppSelector( - state => { - expectTypeOf(state).toEqualTypeOf(rootState) + [ + state => { + expectTypeOf(state).toEqualTypeOf(rootState) - return state.todos - }, - state => { - expectTypeOf(state).toEqualTypeOf(rootState) + return state.todos + }, + state => { + expectTypeOf(state).toEqualTypeOf(rootState) - return state.alerts - }, + return state.alerts + } + ], (todos, alerts) => { // Known limitation: Parameter types are not inferred in this scenario - expectTypeOf(todos).toBeAny() + expectTypeOf(todos).not.toBeAny() - expectTypeOf(alerts).toBeAny() + expectTypeOf(alerts).not.toBeAny() - // @ts-expect-error A typed `createSelector` currently only infers - // the parameter types of the result function when - // input selectors are provided as a single array. return todos.map(({ id }) => id) } ) }) test('can annotate parameter types of the result function to workaround type inference issue', () => { - createAppSelector( - state => state.todos, - (todos: Todo[]) => todos.map(({ id }) => id) + createAppSelector([state => state.todos], todos => + todos.map(({ id }) => id) ) }) }) diff --git a/type-tests/createSelectorCreator.test-d.ts b/type-tests/createSelectorCreator.test-d.ts index e91205f19..22f3e1f6e 100644 --- a/type-tests/createSelectorCreator.test-d.ts +++ b/type-tests/createSelectorCreator.test-d.ts @@ -1,3 +1,4 @@ +import type { AnyFunction } from '@internal/types' import lodashMemoize from 'lodash/memoize' import memoizeOne from 'memoize-one' import microMemoize from 'micro-memoize' @@ -9,6 +10,12 @@ import { } from 'reselect' import { describe, test } from 'vitest' +// Test for exporting declaration of created selector creator +export const testExportStructured = createSelectorCreator( + lruMemoize, + (a, b) => typeof a === typeof b +) + interface RootState { todos: { id: number; completed: boolean }[] alerts: { id: number; read: boolean }[] @@ -25,7 +32,7 @@ const state: RootState = { ] } -describe('createSelectorCreator', () => { +describe('type tests', () => { test('options object as argument', () => { const createSelectorDefault = createSelectorCreator({ memoize: lruMemoize @@ -55,4 +62,67 @@ describe('createSelectorCreator', () => { const createSelectorOne = createSelectorCreator(memoizeOne) const createSelectorLodash = createSelectorCreator(lodashMemoize) }) + + test('createSelectorCreator', () => { + const defaultCreateSelector = createSelectorCreator(lruMemoize) + + const selector = defaultCreateSelector( + (state: { foo: string }) => state.foo, + foo => foo + ) + + expectTypeOf(selector({ foo: 'fizz' })).toBeString() + + expectTypeOf(selector).parameter(1).not.toMatchTypeOf({ bar: 42 }) + + // clearCache should exist because of lruMemoize + expectTypeOf(selector.clearCache).toBeFunction() + + const parametric = defaultCreateSelector( + (state: { foo: string }) => state.foo, + (state: { foo: string }, props: { bar: number }) => props.bar, + (foo, bar) => ({ foo, bar }) + ) + + // @ts-expect-error + parametric({ foo: 'fizz' }) + + const ret = parametric({ foo: 'fizz' }, { bar: 42 }) + + expectTypeOf(ret.foo).toBeString() + + expectTypeOf(ret.bar).toBeNumber() + + // @ts-expect-error + createSelectorCreator(lruMemoize, 1) + + createSelectorCreator(lruMemoize, (a: T, b: T) => { + return `${a}` === `${b}` + }) + }) + + test('custom memoization option types', () => { + const customMemoize = ( + f: AnyFunction, + a: string, + b: number, + c: boolean + ) => { + return f + } + + const customSelectorCreatorCustomMemoizeWorking = createSelectorCreator( + customMemoize, + 'a', + 42, + true + ) + + // @ts-expect-error + const customSelectorCreatorCustomMemoizeMissingArg = createSelectorCreator( + customMemoize, + 'a', + true + ) + }) }) diff --git a/type-tests/createStructuredSelector.test-d.ts b/type-tests/createStructuredSelector.test-d.ts index 864cb44f2..c75516aa7 100644 --- a/type-tests/createStructuredSelector.test-d.ts +++ b/type-tests/createStructuredSelector.test-d.ts @@ -1,12 +1,14 @@ import microMemoize from 'micro-memoize' import type { Selector, TypedStructuredSelectorCreator } from 'reselect' import { + createSelector, createSelectorCreator, createStructuredSelector, lruMemoize, weakMapMemoize } from 'reselect' import { describe, expectTypeOf, test } from 'vitest' +import type { StateAB } from '../test/testTypes' interface Todo { id: number @@ -34,8 +36,7 @@ const rootState: RootState = { ] } -describe('createStructuredSelector', () => { - +describe('type tests', () => { // TODO: Remove this test block once `TypedStructuredSelectorCreator` is removed. test('TypedStructuredSelectorCreator should lock down state type', () => { const createStructuredAppSelector: TypedStructuredSelectorCreator = @@ -43,12 +44,12 @@ describe('createStructuredSelector', () => { const structuredSelector = createStructuredAppSelector({ todos: state => { - expectTypeOf(state).toEqualTypeOf(rootState) + expectTypeOf(state).toEqualTypeOf(rootState) return state.todos }, alerts: state => { - expectTypeOf(state).toEqualTypeOf(rootState) + expectTypeOf(state).toEqualTypeOf(rootState) return state.alerts } @@ -60,13 +61,9 @@ describe('createStructuredSelector', () => { expectTypeOf(alerts).toEqualTypeOf() - expectTypeOf(structuredSelector.argsMemoize).toEqualTypeOf< - typeof weakMapMemoize - >(weakMapMemoize) + expectTypeOf(structuredSelector.argsMemoize).toEqualTypeOf(weakMapMemoize) - expectTypeOf(structuredSelector.memoize).toEqualTypeOf< - typeof weakMapMemoize - >(weakMapMemoize) + expectTypeOf(structuredSelector.memoize).toEqualTypeOf(weakMapMemoize) expectTypeOf(structuredSelector.clearCache).returns.toBeVoid() @@ -90,28 +87,23 @@ describe('createStructuredSelector', () => { () => void >() - expectTypeOf( - structuredSelector.lastResult - ).returns.toEqualTypeOf(rootState) + expectTypeOf(structuredSelector.lastResult).returns.toEqualTypeOf(rootState) expectTypeOf( structuredSelector.memoizedResultFunc - ).parameters.toEqualTypeOf<[Todo[], Alert[]]>([ - rootState.todos, - rootState.alerts - ]) + ).parameters.toEqualTypeOf<[Todo[], Alert[]]>() - expectTypeOf(structuredSelector.memoizedResultFunc).returns.toEqualTypeOf< - ReturnType - >(structuredSelector.lastResult()) + expectTypeOf(structuredSelector.memoizedResultFunc).returns.toEqualTypeOf( + structuredSelector.lastResult() + ) expectTypeOf(structuredSelector.memoizedResultFunc).toHaveProperty( 'clearCache' ) - expectTypeOf(structuredSelector.resultFunc).returns.toEqualTypeOf< - ReturnType - >(structuredSelector.lastResult()) + expectTypeOf(structuredSelector.resultFunc).returns.toEqualTypeOf( + structuredSelector.lastResult() + ) }) // TODO: Remove this test block once `TypedStructuredSelectorCreator` is removed. @@ -132,13 +124,9 @@ describe('createStructuredSelector', () => { createSelectorLru ) - expectTypeOf(structuredSelector.argsMemoize).toEqualTypeOf< - typeof microMemoize - >(microMemoize) + expectTypeOf(structuredSelector.argsMemoize).toEqualTypeOf(microMemoize) - expectTypeOf(structuredSelector.memoize).toEqualTypeOf( - lruMemoize - ) + expectTypeOf(structuredSelector.memoize).toEqualTypeOf(lruMemoize) const { todos, alerts } = structuredSelector(rootState) @@ -164,28 +152,23 @@ describe('createStructuredSelector', () => { () => void >() - expectTypeOf( - structuredSelector.lastResult - ).returns.toEqualTypeOf(rootState) + expectTypeOf(structuredSelector.lastResult).returns.toEqualTypeOf(rootState) expectTypeOf( structuredSelector.memoizedResultFunc - ).parameters.toEqualTypeOf<[Todo[], Alert[]]>([ - rootState.todos, - rootState.alerts - ]) + ).parameters.toEqualTypeOf<[Todo[], Alert[]]>() - expectTypeOf(structuredSelector.memoizedResultFunc).returns.toEqualTypeOf< - ReturnType - >(structuredSelector.lastResult()) + expectTypeOf(structuredSelector.memoizedResultFunc).returns.toEqualTypeOf( + structuredSelector.lastResult() + ) expectTypeOf(structuredSelector.memoizedResultFunc).toHaveProperty( 'clearCache' ) - expectTypeOf(structuredSelector.resultFunc).returns.toEqualTypeOf< - ReturnType - >(structuredSelector.lastResult()) + expectTypeOf(structuredSelector.resultFunc).returns.toEqualTypeOf( + structuredSelector.lastResult() + ) }) test('supports additional parameters', () => { @@ -203,13 +186,9 @@ describe('createStructuredSelector', () => { expectTypeOf(todoById).toEqualTypeOf() - expectTypeOf(structuredSelector.argsMemoize).toEqualTypeOf< - typeof weakMapMemoize - >(weakMapMemoize) + expectTypeOf(structuredSelector.argsMemoize).toEqualTypeOf(weakMapMemoize) - expectTypeOf(structuredSelector.memoize).toEqualTypeOf< - typeof weakMapMemoize - >(weakMapMemoize) + expectTypeOf(structuredSelector.memoize).toEqualTypeOf(weakMapMemoize) expectTypeOf(structuredSelector.clearCache).returns.toBeVoid() @@ -248,26 +227,183 @@ describe('createStructuredSelector', () => { expectTypeOf( structuredSelector.memoizedResultFunc - ).parameters.toEqualTypeOf<[Todo[], Alert[], Todo]>([ - rootState.todos, - rootState.alerts, - rootState.todos[0] - ]) + ).parameters.toEqualTypeOf<[Todo[], Alert[], Todo]>() expectTypeOf(structuredSelector.resultFunc).parameters.toEqualTypeOf< [Todo[], Alert[], Todo] - >([rootState.todos, rootState.alerts, rootState.todos[0]]) + >() - expectTypeOf(structuredSelector.memoizedResultFunc).returns.toEqualTypeOf< - ReturnType - >(structuredSelector.lastResult()) + expectTypeOf(structuredSelector.memoizedResultFunc).returns.toEqualTypeOf( + structuredSelector.lastResult() + ) expectTypeOf(structuredSelector.memoizedResultFunc).toHaveProperty( 'clearCache' ) - expectTypeOf(structuredSelector.resultFunc).returns.toEqualTypeOf< - ReturnType - >(structuredSelector.lastResult()) + expectTypeOf(structuredSelector.resultFunc).returns.toEqualTypeOf( + structuredSelector.lastResult() + ) + }) + + test('automatic inference of types for createStructuredSelector', () => { + const oneParamSelector = createStructuredSelector({ + foo: (state: StateAB) => state.a, + bar: (state: StateAB) => state.b + }) + + const threeParamSelector = createStructuredSelector({ + foo: (state: StateAB, c: number, d: string) => state.a, + bar: (state: StateAB, c: number, d: string) => state.b + }) + + interface State { + foo: string + } + + const FooSelector = (state: State, a: number, b: string) => state.foo + const BarSelector = (state: State, a: number, b: string) => +state.foo + + const selector2 = createStructuredSelector({ + foo: FooSelector, + bar: BarSelector + }) + + const selectorGenerics = createStructuredSelector<{ + foo: typeof FooSelector + bar: typeof BarSelector + }>({ + foo: state => state.foo, + bar: state => +state.foo + }) + + interface ExpectedResult { + foo: string + bar: number + } + + const resOneParam = oneParamSelector({ a: 1, b: 2 }) + const resThreeParams = threeParamSelector({ a: 1, b: 2 }, 99, 'blah') + const res3: ExpectedResult = selector2({ foo: '42' }, 99, 'test') + const resGenerics: ExpectedResult = selectorGenerics( + { foo: '42' }, + 99, + 'test' + ) + + //@ts-expect-error + selector2({ bar: '42' }) + // @ts-expect-error + selectorGenerics({ bar: '42' }) + }) + + test('structured selector type parameters', () => { + interface GlobalState { + foo: string + bar: number + } + + const selectFoo = (state: GlobalState) => state.foo + const selectBar = (state: GlobalState) => state.bar + + // Output state should be the same as input, if not provided + // @ts-expect-error + createStructuredSelector({ + foo: selectFoo + // bar: selectBar, + // ^^^ because this is missing, an error is thrown + }) + }) + + test("issue #548: createStructuredSelector doesn't infer props typings", () => { + // https://github.com/reduxjs/reselect/issues/548 + + interface State { + value: Record | null + loading: boolean + } + + interface Props { + currency: string + } + + const isLoading = createSelector( + (state: State) => state, + (_: State, props: Props) => props.currency, + ({ loading }, currency) => loading + ) + + const mapData = createStructuredSelector({ + isLoading, + test2: (state: State) => 42 + }) + + const result = mapData({ value: null, loading: false }, { currency: 'EUR' }) + }) + + test('verify structured selector matches createSelector in output structure and type definitions', () => { + // A structured selector created by `createStructuredSelector` + // is the same as a selector created by `createSelector` when it + // returns an object made up of selectors + + const createSelectorMicro = createSelectorCreator({ + memoize: microMemoize, + argsMemoize: microMemoize + }) + + const selector = createSelectorMicro( + [ + (state: RootState) => state.todos, + (state: RootState) => state.alerts, + (state: RootState, id: number) => state.todos[id] + ], + (todos, alerts, todoById) => ({ todos, alerts, todoById }) + ) + + const structuredSelector = createStructuredSelector( + { + todos: (state: RootState) => state.todos, + alerts: (state: RootState) => state.alerts, + todoById: (state: RootState, id: number) => state.todos[id] + }, + + createSelectorMicro + ) + + expectTypeOf(structuredSelector).toEqualTypeOf(selector) + + expectTypeOf(structuredSelector.memoizedResultFunc).toHaveProperty('cache') + + expectTypeOf(structuredSelector.memoizedResultFunc).toHaveProperty('fn') + + expectTypeOf(structuredSelector.memoizedResultFunc).toHaveProperty( + 'isMemoized' + ) + + expectTypeOf(structuredSelector.memoizedResultFunc).toHaveProperty( + 'options' + ) + expectTypeOf(selector.memoizedResultFunc).toHaveProperty('cache') + + expectTypeOf(selector.memoizedResultFunc).toHaveProperty('fn') + + expectTypeOf(selector.memoizedResultFunc).toHaveProperty('isMemoized') + + expectTypeOf(selector.memoizedResultFunc).toHaveProperty('options') + + expectTypeOf(structuredSelector.argsMemoize).toEqualTypeOf(microMemoize) + + expectTypeOf(structuredSelector.memoize).toEqualTypeOf(microMemoize) + + expectTypeOf(structuredSelector.dependencies).toEqualTypeOf< + [ + (state: RootState) => Todo[], + (state: RootState) => Alert[], + (state: RootState, id: number) => Todo + ] + >() + + // @ts-expect-error Wrong number of arguments. + structuredSelector(state, 2) }) }) diff --git a/type-tests/createStructuredSelector.withTypes.test-d.ts b/type-tests/createStructuredSelector.withTypes.test-d.ts index 9bb5b1ff7..98d3aba71 100644 --- a/type-tests/createStructuredSelector.withTypes.test-d.ts +++ b/type-tests/createStructuredSelector.withTypes.test-d.ts @@ -39,7 +39,7 @@ const rootState: RootState = { ] } -describe('createStructuredSelector.withTypes()', () => { +describe('type tests', () => { const createStructuredAppSelector = createStructuredSelector.withTypes() @@ -50,12 +50,12 @@ describe('createStructuredSelector.withTypes()', () => { const structuredAppSelector = createStructuredAppSelector({ todos: state => { - expectTypeOf(state).toEqualTypeOf(rootState) + expectTypeOf(state).toEqualTypeOf(rootState) return state.todos }, alerts: state => { - expectTypeOf(state).toEqualTypeOf(rootState) + expectTypeOf(state).toEqualTypeOf(rootState) return state.alerts } @@ -67,13 +67,11 @@ describe('createStructuredSelector.withTypes()', () => { expectTypeOf(alerts).toEqualTypeOf() - expectTypeOf(structuredAppSelector.argsMemoize).toEqualTypeOf< - typeof weakMapMemoize - >(weakMapMemoize) + expectTypeOf(structuredAppSelector.argsMemoize).toEqualTypeOf( + weakMapMemoize + ) - expectTypeOf(structuredAppSelector.memoize).toEqualTypeOf< - typeof weakMapMemoize - >(weakMapMemoize) + expectTypeOf(structuredAppSelector.memoize).toEqualTypeOf(weakMapMemoize) expectTypeOf(structuredAppSelector.clearCache).returns.toBeVoid() @@ -99,30 +97,25 @@ describe('createStructuredSelector.withTypes()', () => { () => void >() - expectTypeOf( - structuredAppSelector.lastResult - ).returns.toEqualTypeOf(rootState) + expectTypeOf(structuredAppSelector.lastResult).returns.toEqualTypeOf( + rootState + ) expectTypeOf( structuredAppSelector.memoizedResultFunc - ).parameters.toEqualTypeOf<[Todo[], Alert[]]>([ - rootState.todos, - rootState.alerts - ]) + ).parameters.toEqualTypeOf<[Todo[], Alert[]]>() expectTypeOf( structuredAppSelector.memoizedResultFunc - ).returns.toEqualTypeOf< - ReturnType - >(structuredAppSelector.lastResult()) + ).returns.toEqualTypeOf(structuredAppSelector.lastResult()) expectTypeOf(structuredAppSelector.memoizedResultFunc).toHaveProperty( 'clearCache' ) - expectTypeOf(structuredAppSelector.resultFunc).returns.toEqualTypeOf< - ReturnType - >(structuredAppSelector.lastResult()) + expectTypeOf(structuredAppSelector.resultFunc).returns.toEqualTypeOf( + structuredAppSelector.lastResult() + ) }) test('should correctly infer memoize and argsMemoize', () => { @@ -139,13 +132,9 @@ describe('createStructuredSelector.withTypes()', () => { createSelectorLru ) - expectTypeOf(structuredSelector.argsMemoize).toEqualTypeOf< - typeof microMemoize - >(microMemoize) + expectTypeOf(structuredSelector.argsMemoize).toEqualTypeOf(microMemoize) - expectTypeOf(structuredSelector.memoize).toEqualTypeOf( - lruMemoize - ) + expectTypeOf(structuredSelector.memoize).toEqualTypeOf(lruMemoize) const { todos, alerts } = structuredSelector(rootState) @@ -171,44 +160,39 @@ describe('createStructuredSelector.withTypes()', () => { () => void >() - expectTypeOf( - structuredSelector.lastResult - ).returns.toEqualTypeOf(rootState) + expectTypeOf(structuredSelector.lastResult).returns.toEqualTypeOf(rootState) expectTypeOf( structuredSelector.memoizedResultFunc - ).parameters.toEqualTypeOf<[Todo[], Alert[]]>([ - rootState.todos, - rootState.alerts - ]) + ).parameters.toEqualTypeOf<[Todo[], Alert[]]>() - expectTypeOf(structuredSelector.memoizedResultFunc).returns.toEqualTypeOf< - ReturnType - >(structuredSelector.lastResult()) + expectTypeOf(structuredSelector.memoizedResultFunc).returns.toEqualTypeOf( + structuredSelector.lastResult() + ) expectTypeOf(structuredSelector.memoizedResultFunc).toHaveProperty( 'clearCache' ) - expectTypeOf(structuredSelector.resultFunc).returns.toEqualTypeOf< - ReturnType - >(structuredSelector.lastResult()) + expectTypeOf(structuredSelector.resultFunc).returns.toEqualTypeOf( + structuredSelector.lastResult() + ) }) test('supports additional parameters', () => { const structuredAppSelector = createStructuredAppSelector({ todos: state => { - expectTypeOf(state).toEqualTypeOf(rootState) + expectTypeOf(state).toEqualTypeOf(rootState) return state.todos }, alerts: state => { - expectTypeOf(state).toEqualTypeOf(rootState) + expectTypeOf(state).toEqualTypeOf(rootState) return state.alerts }, todoById: (state, id: number) => { - expectTypeOf(state).toEqualTypeOf(rootState) + expectTypeOf(state).toEqualTypeOf(rootState) return state.todos[id] } @@ -222,13 +206,11 @@ describe('createStructuredSelector.withTypes()', () => { expectTypeOf(todoById).toEqualTypeOf() - expectTypeOf(structuredAppSelector.argsMemoize).toEqualTypeOf< - typeof weakMapMemoize - >(weakMapMemoize) + expectTypeOf(structuredAppSelector.argsMemoize).toEqualTypeOf( + weakMapMemoize + ) - expectTypeOf(structuredAppSelector.memoize).toEqualTypeOf< - typeof weakMapMemoize - >(weakMapMemoize) + expectTypeOf(structuredAppSelector.memoize).toEqualTypeOf(weakMapMemoize) expectTypeOf(structuredAppSelector.clearCache).returns.toBeVoid() @@ -269,29 +251,23 @@ describe('createStructuredSelector.withTypes()', () => { expectTypeOf( structuredAppSelector.memoizedResultFunc - ).parameters.toEqualTypeOf<[Todo[], Alert[], Todo]>([ - rootState.todos, - rootState.alerts, - rootState.todos[0] - ]) + ).parameters.toEqualTypeOf<[Todo[], Alert[], Todo]>() expectTypeOf(structuredAppSelector.resultFunc).parameters.toEqualTypeOf< [Todo[], Alert[], Todo] - >([rootState.todos, rootState.alerts, rootState.todos[0]]) + >() expectTypeOf( structuredAppSelector.memoizedResultFunc - ).returns.toEqualTypeOf< - ReturnType - >(structuredAppSelector.lastResult()) + ).returns.toEqualTypeOf(structuredAppSelector.lastResult()) expectTypeOf(structuredAppSelector.memoizedResultFunc).toHaveProperty( 'clearCache' ) - expectTypeOf(structuredAppSelector.resultFunc).returns.toEqualTypeOf< - ReturnType - >(structuredAppSelector.lastResult()) + expectTypeOf(structuredAppSelector.resultFunc).returns.toEqualTypeOf( + structuredAppSelector.lastResult() + ) }) // TODO: Remove this test block once `TypedStructuredSelectorCreator` is removed. @@ -301,12 +277,12 @@ describe('createStructuredSelector.withTypes()', () => { const structuredAppSelector = createStructuredAppSelector({ todos: state => { - expectTypeOf(state).toEqualTypeOf(rootState) + expectTypeOf(state).toEqualTypeOf(rootState) return state.todos }, alerts: state => { - expectTypeOf(state).toEqualTypeOf(rootState) + expectTypeOf(state).toEqualTypeOf(rootState) return state.alerts } @@ -318,13 +294,11 @@ describe('createStructuredSelector.withTypes()', () => { expectTypeOf(alerts).toEqualTypeOf() - expectTypeOf(structuredAppSelector.argsMemoize).toEqualTypeOf< - typeof weakMapMemoize - >(weakMapMemoize) + expectTypeOf(structuredAppSelector.argsMemoize).toEqualTypeOf( + weakMapMemoize + ) - expectTypeOf(structuredAppSelector.memoize).toEqualTypeOf< - typeof weakMapMemoize - >(weakMapMemoize) + expectTypeOf(structuredAppSelector.memoize).toEqualTypeOf(weakMapMemoize) expectTypeOf(structuredAppSelector.clearCache).returns.toBeVoid() @@ -350,42 +324,37 @@ describe('createStructuredSelector.withTypes()', () => { () => void >() - expectTypeOf( - structuredAppSelector.lastResult - ).returns.toEqualTypeOf(rootState) + expectTypeOf(structuredAppSelector.lastResult).returns.toEqualTypeOf( + rootState + ) expectTypeOf( structuredAppSelector.memoizedResultFunc - ).parameters.toEqualTypeOf<[Todo[], Alert[]]>([ - rootState.todos, - rootState.alerts - ]) + ).parameters.toEqualTypeOf<[Todo[], Alert[]]>() expectTypeOf( structuredAppSelector.memoizedResultFunc - ).returns.toEqualTypeOf< - ReturnType - >(structuredAppSelector.lastResult()) + ).returns.toEqualTypeOf(structuredAppSelector.lastResult()) expectTypeOf(structuredAppSelector.memoizedResultFunc).toHaveProperty( 'clearCache' ) - expectTypeOf(structuredAppSelector.resultFunc).returns.toEqualTypeOf< - ReturnType - >(structuredAppSelector.lastResult()) + expectTypeOf(structuredAppSelector.resultFunc).returns.toEqualTypeOf( + structuredAppSelector.lastResult() + ) }) test('should work with createSelector.withTypes()', () => { const structuredAppSelector = createStructuredAppSelector( { todos: state => { - expectTypeOf(state).toEqualTypeOf(rootState) + expectTypeOf(state).toEqualTypeOf(rootState) return state.todos }, alerts: state => { - expectTypeOf(state).toEqualTypeOf(rootState) + expectTypeOf(state).toEqualTypeOf(rootState) return state.alerts } @@ -399,13 +368,11 @@ describe('createStructuredSelector.withTypes()', () => { expectTypeOf(alerts).toEqualTypeOf() - expectTypeOf(structuredAppSelector.argsMemoize).toEqualTypeOf< - typeof weakMapMemoize - >(weakMapMemoize) + expectTypeOf(structuredAppSelector.argsMemoize).toEqualTypeOf( + weakMapMemoize + ) - expectTypeOf(structuredAppSelector.memoize).toEqualTypeOf< - typeof weakMapMemoize - >(weakMapMemoize) + expectTypeOf(structuredAppSelector.memoize).toEqualTypeOf(weakMapMemoize) expectTypeOf(structuredAppSelector.clearCache).returns.toBeVoid() @@ -431,30 +398,25 @@ describe('createStructuredSelector.withTypes()', () => { () => void >() - expectTypeOf( - structuredAppSelector.lastResult - ).returns.toEqualTypeOf(rootState) + expectTypeOf(structuredAppSelector.lastResult).returns.toEqualTypeOf( + rootState + ) expectTypeOf( structuredAppSelector.memoizedResultFunc - ).parameters.toEqualTypeOf<[Todo[], Alert[]]>([ - rootState.todos, - rootState.alerts - ]) + ).parameters.toEqualTypeOf<[Todo[], Alert[]]>() expectTypeOf( structuredAppSelector.memoizedResultFunc - ).returns.toEqualTypeOf< - ReturnType - >(structuredAppSelector.lastResult()) + ).returns.toEqualTypeOf(structuredAppSelector.lastResult()) expectTypeOf(structuredAppSelector.memoizedResultFunc).toHaveProperty( 'clearCache' ) - expectTypeOf(structuredAppSelector.resultFunc).returns.toEqualTypeOf< - ReturnType - >(structuredAppSelector.lastResult()) + expectTypeOf(structuredAppSelector.resultFunc).returns.toEqualTypeOf( + structuredAppSelector.lastResult() + ) }) test('StructuredSelectorCreator should lock down the state type', () => { @@ -464,12 +426,12 @@ describe('createStructuredSelector.withTypes()', () => { const structuredAppSelector = createStructuredAppSelector( { todos: state => { - expectTypeOf(state).toEqualTypeOf(rootState) + expectTypeOf(state).toEqualTypeOf(rootState) return state.todos }, alerts: state => { - expectTypeOf(state).toEqualTypeOf(rootState) + expectTypeOf(state).toEqualTypeOf(rootState) return state.alerts } @@ -483,13 +445,11 @@ describe('createStructuredSelector.withTypes()', () => { expectTypeOf(alerts).toEqualTypeOf() - expectTypeOf(structuredAppSelector.argsMemoize).toEqualTypeOf< - typeof weakMapMemoize - >(weakMapMemoize) + expectTypeOf(structuredAppSelector.argsMemoize).toEqualTypeOf( + weakMapMemoize + ) - expectTypeOf(structuredAppSelector.memoize).toEqualTypeOf< - typeof weakMapMemoize - >(weakMapMemoize) + expectTypeOf(structuredAppSelector.memoize).toEqualTypeOf(weakMapMemoize) expectTypeOf(structuredAppSelector.clearCache).returns.toBeVoid() @@ -515,29 +475,24 @@ describe('createStructuredSelector.withTypes()', () => { () => void >() - expectTypeOf( - structuredAppSelector.lastResult - ).returns.toEqualTypeOf(rootState) + expectTypeOf(structuredAppSelector.lastResult).returns.toEqualTypeOf( + rootState + ) expectTypeOf( structuredAppSelector.memoizedResultFunc - ).parameters.toEqualTypeOf<[Todo[], Alert[]]>([ - rootState.todos, - rootState.alerts - ]) + ).parameters.toEqualTypeOf<[Todo[], Alert[]]>() expectTypeOf( structuredAppSelector.memoizedResultFunc - ).returns.toEqualTypeOf< - ReturnType - >(structuredAppSelector.lastResult()) + ).returns.toEqualTypeOf(structuredAppSelector.lastResult()) expectTypeOf(structuredAppSelector.memoizedResultFunc).toHaveProperty( 'clearCache' ) - expectTypeOf(structuredAppSelector.resultFunc).returns.toEqualTypeOf< - ReturnType - >(structuredAppSelector.lastResult()) + expectTypeOf(structuredAppSelector.resultFunc).returns.toEqualTypeOf( + structuredAppSelector.lastResult() + ) }) }) diff --git a/type-tests/deepNesting.test-d.ts b/type-tests/deepNesting.test-d.ts index e602026f1..b7af9df5a 100644 --- a/type-tests/deepNesting.test-d.ts +++ b/type-tests/deepNesting.test-d.ts @@ -1,3 +1,5 @@ +import type { AnyFunction } from '@internal/types' +import type { Cache } from 'micro-memoize' import microMemoize from 'micro-memoize' import { createSelector, lruMemoize } from 'reselect' import { describe, test } from 'vitest' @@ -16,12 +18,13 @@ const state: RootState = { ] } -describe('deep nesting', () => { - test('Deep Nesting First And Second createSelector Overload', () => { - type State = { foo: string } - const readOne = (state: State) => state.foo +describe('type tests', () => { + test('issue #525: verify more than 12 selectors are accepted', () => { + // https://github.com/reduxjs/reselect/issues/525 - const selector0 = createSelector(readOne, one => one) + const selectTodos = (state: RootState) => state.todos + + const selector0 = createSelector(selectTodos, todos => todos) const selector1 = createSelector(selector0, s => s) const selector2 = createSelector(selector1, s => s) const selector3 = createSelector(selector2, s => s) @@ -34,9 +37,15 @@ describe('deep nesting', () => { const selector10 = createSelector(selector9, s => s, { memoize: microMemoize }) - selector10.dependencies[0].dependencies[0].dependencies[0].dependencies[0] - .dependencies[0].dependencies[0].dependencies[0].dependencies[0] - .dependencies[0].dependencies[0].memoizedResultFunc.clearCache + + expectTypeOf(selector10).toBeCallableWith(state) + + expectTypeOf( + selector10.dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].memoizedResultFunc.clearCache + ).toEqualTypeOf<() => void>() + const selector11 = createSelector(selector10, s => s) const selector12 = createSelector(selector11, s => s) const selector13 = createSelector(selector12, s => s) @@ -47,9 +56,15 @@ describe('deep nesting', () => { const selector18 = createSelector(selector17, s => s) const selector19 = createSelector(selector18, s => s) const selector20 = createSelector(selector19, s => s) - selector20.dependencies[0].dependencies[0].dependencies[0].dependencies[0] - .dependencies[0].dependencies[0].dependencies[0].dependencies[0] - .dependencies[0].dependencies[0].memoizedResultFunc.cache + + expectTypeOf(selector20).toBeCallableWith(state) + + expectTypeOf( + selector20.dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].memoizedResultFunc.cache + ).toEqualTypeOf>() + const selector21 = createSelector(selector20, s => s) const selector22 = createSelector(selector21, s => s) const selector23 = createSelector(selector22, s => s) @@ -60,20 +75,25 @@ describe('deep nesting', () => { const selector28 = createSelector(selector27, s => s) const selector29 = createSelector(selector28, s => s) const selector30 = createSelector(selector29, s => s) - selector30.dependencies[0].dependencies[0].dependencies[0].dependencies[0] - .dependencies[0].dependencies[0].dependencies[0].dependencies[0] - .dependencies[0].dependencies[0].dependencies[0].dependencies[0] - .dependencies[0].dependencies[0].dependencies[0].dependencies[0] - .dependencies[0].dependencies[0].dependencies[0].dependencies[0] - .dependencies[0].dependencies[0].dependencies[0].dependencies[0] - .dependencies[0].dependencies[0].dependencies[0].dependencies[0] - .dependencies[0].dependencies[0].memoizedResultFunc.clearCache + + expectTypeOf(selector30).toBeCallableWith(state) + + expectTypeOf( + selector30.dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].memoizedResultFunc.clearCache + ).toEqualTypeOf<() => void>() }) + test('Deep Nesting Second createSelector Overload', () => { - type State = { foo: string } - const readOne = (state: State) => state.foo + const selectTodos = (state: RootState) => state.todos - const selector0 = createSelector(readOne, one => one) + const selector0 = createSelector(selectTodos, todos => todos) const selector1 = createSelector(selector0, s => s, { memoize: lruMemoize }) @@ -104,6 +124,15 @@ describe('deep nesting', () => { const selector10 = createSelector(selector9, s => s, { memoize: lruMemoize }) + + expectTypeOf(selector10).toBeCallableWith(state) + + expectTypeOf( + selector10.dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].memoizedResultFunc.clearCache + ).toEqualTypeOf<() => void>() + const selector11 = createSelector(selector10, s => s, { memoize: lruMemoize }) @@ -134,6 +163,15 @@ describe('deep nesting', () => { const selector20 = createSelector(selector19, s => s, { memoize: lruMemoize }) + + expectTypeOf(selector20).toBeCallableWith(state) + + expectTypeOf( + selector20.dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].memoizedResultFunc.clearCache + ).toEqualTypeOf<() => void>() + const selector21 = createSelector(selector20, s => s, { memoize: lruMemoize }) @@ -161,13 +199,28 @@ describe('deep nesting', () => { const selector29 = createSelector(selector28, s => s, { memoize: lruMemoize }) + const selector30 = createSelector(selector29, s => s, { + memoize: lruMemoize + }) + + expectTypeOf(selector30).toBeCallableWith(state) + + expectTypeOf( + selector30.dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].memoizedResultFunc.clearCache + ).toEqualTypeOf<() => void>() }) test('Deep Nesting Third createSelector Overload', () => { - type State = { foo: string } - const readOne = (state: State) => state.foo + const selectTodos = (state: RootState) => state.todos - const selector0 = createSelector(readOne, one => one) + const selector0 = createSelector(selectTodos, todos => todos) const selector1 = createSelector([selector0], s => s) const selector2 = createSelector([selector1], s => s) const selector3 = createSelector([selector2], s => s) @@ -178,6 +231,15 @@ describe('deep nesting', () => { const selector8 = createSelector([selector7], s => s) const selector9 = createSelector([selector8], s => s) const selector10 = createSelector([selector9], s => s) + + expectTypeOf(selector10).toBeCallableWith(state) + + expectTypeOf( + selector10.dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].memoizedResultFunc.clearCache + ).toEqualTypeOf<() => void>() + const selector11 = createSelector([selector10], s => s) const selector12 = createSelector([selector11], s => s) const selector13 = createSelector([selector12], s => s) @@ -188,6 +250,15 @@ describe('deep nesting', () => { const selector18 = createSelector([selector17], s => s) const selector19 = createSelector([selector18], s => s) const selector20 = createSelector([selector19], s => s) + + expectTypeOf(selector20).toBeCallableWith(state) + + expectTypeOf( + selector20.dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].memoizedResultFunc.clearCache + ).toEqualTypeOf<() => void>() + const selector21 = createSelector([selector20], s => s) const selector22 = createSelector([selector21], s => s) const selector23 = createSelector([selector22], s => s) @@ -198,6 +269,19 @@ describe('deep nesting', () => { const selector28 = createSelector([selector27], s => s) const selector29 = createSelector([selector28], s => s) const selector30 = createSelector([selector29], s => s) + + expectTypeOf(selector30).toBeCallableWith(state) + + expectTypeOf( + selector30.dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].dependencies[0].dependencies[0] + .dependencies[0].dependencies[0].memoizedResultFunc.clearCache + ).toEqualTypeOf<() => void>() }) test('createSelector Parameter Limit', () => { @@ -317,4 +401,34 @@ describe('deep nesting', () => { } ) }) + + test('nested selector', () => { + interface State { + foo: string + bar: number + baz: boolean + } + + const selector = createSelector( + createSelector( + (state: State) => state.foo, + (state: State) => state.bar, + (foo, bar) => ({ foo, bar }) + ), + (state: State) => state.baz, + ({ foo, bar }, baz) => { + const foo1: string = foo + // @ts-expect-error + const foo2: number = foo + + const bar1: number = bar + // @ts-expect-error + const bar2: string = bar + + const baz1: boolean = baz + // @ts-expect-error + const baz2: string = baz + } + ) + }) }) diff --git a/type-tests/lruMemoize.test-d.ts b/type-tests/lruMemoize.test-d.ts new file mode 100644 index 000000000..f1543941b --- /dev/null +++ b/type-tests/lruMemoize.test-d.ts @@ -0,0 +1,93 @@ +import type { AnyFunction } from '@internal/types' +import { groupBy, isEqual } from 'lodash' +import { + createSelectorCreator, + lruMemoize, + referenceEqualityCheck +} from 'reselect' + +describe('type tests', () => { + test('lruMemoize', () => { + const func = (a: string) => +a + + const memoized = lruMemoize(func) + + expectTypeOf(memoized('42')).toBeNumber() + + expectTypeOf(memoized('42')).not.toBeString() + + const memoized2 = lruMemoize( + (str: string, arr: string[]): { str: string; arr: string[] } => ({ + str, + arr + }), + (a: T, b: T) => { + return `${a}` === `${b}` + } + ) + + const ret2 = memoized2('', ['1', '2']) + + expectTypeOf(ret2.str).toBeString() + + expectTypeOf(ret2.arr).items.toBeString() + }) + + test('issue #384', () => { + // https://github.com/reduxjs/reselect/issues/384 + + function multiArgMemoize( + func: F, + a: number, + b: string, + equalityCheck = referenceEqualityCheck + ): F { + return func + } + + interface Transaction { + transactionId: string + } + + const toId = (transaction: Transaction) => transaction.transactionId + + const transactionsIds = (transactions: Transaction[]) => + transactions.map(toId) + + const collectionsEqual = (ts1: Transaction[], ts2: Transaction[]) => + isEqual(transactionsIds(ts1), transactionsIds(ts2)) + + expectTypeOf(createSelectorCreator).toBeCallableWith( + lruMemoize, + collectionsEqual + ) + + const createMultiMemoizeArgSelector = createSelectorCreator( + multiArgMemoize, + 42, + 'abcd', + referenceEqualityCheck + ) + + const select = createMultiMemoizeArgSelector( + (state: { foo: string }) => state.foo, + foo => `${foo}!` + ) + + // error is not applicable anymore + expectTypeOf(select.clearCache).toBeFunction() + + const createMultiMemoizeArgSelector2 = createSelectorCreator( + multiArgMemoize, + 42, + // @ts-expect-error + referenceEqualityCheck + ) + + expectTypeOf(lruMemoize).toBeCallableWith( + (transactions: Transaction[]) => + groupBy(transactions, item => item.transactionId), + collectionsEqual + ) + }) +}) diff --git a/type-tests/tsconfig.json b/type-tests/tsconfig.json deleted file mode 100644 index 4fae7b4d6..000000000 --- a/type-tests/tsconfig.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs", - "esModuleInterop": true, - "strict": true, - "target": "ES2015", - "lib": ["ES2021.WeakRef"], - "declaration": true, - "noEmit": true, - "skipLibCheck": true, - "paths": { - "reselect": ["../src/index"], // @remap-prod-remove-line - "@internal/*": ["../src/*"] - } - }, - "include": ["**/*.ts", "../typescript_test/**/*.ts"] -} diff --git a/typescript_test/argsMemoize.typetest.ts b/typescript_test/argsMemoize.typetest.ts deleted file mode 100644 index 1e883ab99..000000000 --- a/typescript_test/argsMemoize.typetest.ts +++ /dev/null @@ -1,1160 +0,0 @@ -import memoizeOne from 'memoize-one' -import microMemoize from 'micro-memoize' -import { - unstable_autotrackMemoize as autotrackMemoize, - createSelector, - createSelectorCreator, - lruMemoize, - weakMapMemoize -} from 'reselect' -import { expectExactType } from './typesTestUtils' - -interface RootState { - todos: { - id: number - completed: boolean - }[] -} -const state: RootState = { - todos: [ - { id: 0, completed: false }, - { id: 1, completed: false } - ] -} - -function overrideOnlyMemoizeInCreateSelector() { - const selectorDefaultSeparateInlineArgs = createSelector( - (state: RootState) => state.todos, - todos => todos.map(t => t.id), - { memoize: lruMemoize } - ) - const selectorDefaultArgsAsArray = createSelector( - [(state: RootState) => state.todos], - todos => todos.map(t => t.id), - { memoize: lruMemoize } - ) - const selectorDefaultArgsAsArrayWithMemoizeOptions = createSelector( - [(state: RootState) => state.todos], - todos => todos.map(t => t.id), - { memoize: lruMemoize, memoizeOptions: { maxSize: 2 } } - ) - const selectorDefaultSeparateInlineArgsWithMemoizeOptions = createSelector( - (state: RootState) => state.todos, - todos => todos.map(t => t.id), - { memoize: lruMemoize, memoizeOptions: { maxSize: 2 } } - ) - const selectorAutotrackSeparateInlineArgs = createSelector( - (state: RootState) => state.todos, - todos => todos.map(t => t.id), - { memoize: autotrackMemoize } - ) - const selectorAutotrackArgsAsArray = createSelector( - [(state: RootState) => state.todos], - todos => todos.map(t => t.id), - { memoize: autotrackMemoize } - ) - // @ts-expect-error When memoize is autotrackMemoize, type of memoizeOptions needs to be the same as options args in autotrackMemoize. - const selectorAutotrackArgsAsArrayWithMemoizeOptions = createSelector( - [(state: RootState) => state.todos], - // @ts-expect-error - todos => todos.map(t => t.id), - { memoize: autotrackMemoize, memoizeOptions: { maxSize: 2 } } - ) - // @ts-expect-error When memoize is autotrackMemoize, type of memoizeOptions needs to be the same as options args in autotrackMemoize. - const selectorAutotrackSeparateInlineArgsWithMemoizeOptions = createSelector( - (state: RootState) => state.todos, - // @ts-expect-error - todos => todos.map(t => t.id), - { memoize: autotrackMemoize, memoizeOptions: { maxSize: 2 } } - ) - const selectorWeakMapSeparateInlineArgs = createSelector( - (state: RootState) => state.todos, - todos => todos.map(t => t.id), - { memoize: weakMapMemoize } - ) - const selectorWeakMapArgsAsArray = createSelector( - [(state: RootState) => state.todos], - todos => todos.map(t => t.id), - { memoize: weakMapMemoize } - ) - // @ts-expect-error When memoize is weakMapMemoize, type of memoizeOptions needs to be the same as options args in weakMapMemoize. - const selectorWeakMapArgsAsArrayWithMemoizeOptions = createSelector( - [(state: RootState) => state.todos], - // @ts-expect-error - todos => todos.map(t => t.id), - { memoize: weakMapMemoize, memoizeOptions: { maxSize: 2 } } - ) - // @ts-expect-error When memoize is weakMapMemoize, type of memoizeOptions needs to be the same as options args in weakMapMemoize. - const selectorWeakMapSeparateInlineArgsWithMemoizeOptions = createSelector( - (state: RootState) => state.todos, - // @ts-expect-error - todos => todos.map(t => t.id), - { memoize: weakMapMemoize, memoizeOptions: { maxSize: 2 } } - ) - const createSelectorDefault = createSelectorCreator(lruMemoize) - const createSelectorWeakMap = createSelectorCreator(weakMapMemoize) - const createSelectorAutotrack = createSelectorCreator(autotrackMemoize) - const changeMemoizeMethodSelectorDefault = createSelectorDefault( - (state: RootState) => state.todos, - todos => todos.map(t => t.id), - { memoize: weakMapMemoize } - ) - const changeMemoizeMethodSelectorWeakMap = createSelectorWeakMap( - (state: RootState) => state.todos, - todos => todos.map(t => t.id), - { memoize: lruMemoize } - ) - const changeMemoizeMethodSelectorAutotrack = createSelectorAutotrack( - (state: RootState) => state.todos, - todos => todos.map(t => t.id), - { memoize: lruMemoize } - ) - const changeMemoizeMethodSelectorDefaultWithMemoizeOptions = - // @ts-expect-error When memoize is changed to weakMapMemoize or autotrackMemoize, memoizeOptions cannot be the same type as options args in lruMemoize. - createSelectorDefault( - (state: RootState) => state.todos, - // @ts-expect-error - todos => todos.map(t => t.id), - { memoize: weakMapMemoize, memoizeOptions: { maxSize: 2 } } - ) - const changeMemoizeMethodSelectorWeakMapWithMemoizeOptions = - createSelectorWeakMap( - (state: RootState) => state.todos, - todos => todos.map(t => t.id), - { memoize: lruMemoize, memoizeOptions: { maxSize: 2 } } // When memoize is changed to lruMemoize, memoizeOptions can now be the same type as options args in lruMemoize. - ) - const changeMemoizeMethodSelectorAutotrackWithMemoizeOptions = - createSelectorAutotrack( - (state: RootState) => state.todos, - todos => todos.map(t => t.id), - { memoize: lruMemoize, memoizeOptions: { maxSize: 2 } } // When memoize is changed to lruMemoize, memoizeOptions can now be the same type as options args in lruMemoize. - ) -} - -function overrideOnlyArgsMemoizeInCreateSelector() { - const selectorDefaultSeparateInlineArgs = createSelector( - (state: RootState) => state.todos, - todos => todos.map(t => t.id), - { argsMemoize: lruMemoize } - ) - const selectorDefaultArgsAsArray = createSelector( - [(state: RootState) => state.todos], - todos => todos.map(t => t.id), - { argsMemoize: lruMemoize } - ) - const selectorDefaultArgsAsArrayWithMemoizeOptions = createSelector( - [(state: RootState) => state.todos], - todos => todos.map(t => t.id), - { argsMemoize: lruMemoize, argsMemoizeOptions: { maxSize: 2 } } - ) - const selectorDefaultSeparateInlineArgsWithMemoizeOptions = createSelector( - (state: RootState) => state.todos, - todos => todos.map(t => t.id), - { argsMemoize: lruMemoize, argsMemoizeOptions: { maxSize: 2 } } - ) - const selectorAutotrackSeparateInlineArgs = createSelector( - (state: RootState) => state.todos, - todos => todos.map(t => t.id), - { argsMemoize: autotrackMemoize } - ) - const selectorAutotrackArgsAsArray = createSelector( - [(state: RootState) => state.todos], - todos => todos.map(t => t.id), - { argsMemoize: autotrackMemoize } - ) - // @ts-expect-error When argsMemoize is autotrackMemoize, type of argsMemoizeOptions needs to be the same as options args in autotrackMemoize. - const selectorAutotrackArgsAsArrayWithMemoizeOptions = createSelector( - [(state: RootState) => state.todos], - // @ts-expect-error - todos => todos.map(t => t.id), - { - argsMemoize: autotrackMemoize, - argsMemoizeOptions: { maxSize: 2 } - } - ) - // @ts-expect-error When argsMemoize is autotrackMemoize, type of argsMemoizeOptions needs to be the same as options args in autotrackMemoize. - const selectorAutotrackSeparateInlineArgsWithMemoizeOptions = createSelector( - (state: RootState) => state.todos, - // @ts-expect-error - todos => todos.map(t => t.id), - { - argsMemoize: autotrackMemoize, - argsMemoizeOptions: { maxSize: 2 } - } - ) - const selectorWeakMapSeparateInlineArgs = createSelector( - (state: RootState) => state.todos, - todos => todos.map(t => t.id), - { argsMemoize: weakMapMemoize } - ) - const selectorWeakMapArgsAsArray = createSelector( - [(state: RootState) => state.todos], - todos => todos.map(t => t.id), - { argsMemoize: weakMapMemoize } - ) - // @ts-expect-error When argsMemoize is weakMapMemoize, type of argsMemoizeOptions needs to be the same as options args in weakMapMemoize. - const selectorWeakMapArgsAsArrayWithMemoizeOptions = createSelector( - [(state: RootState) => state.todos], - // @ts-expect-error - todos => todos.map(t => t.id), - { argsMemoize: weakMapMemoize, argsMemoizeOptions: { maxSize: 2 } } - ) - // @ts-expect-error When argsMemoize is weakMapMemoize, type of argsMemoizeOptions needs to be the same as options args in weakMapMemoize. - const selectorWeakMapSeparateInlineArgsWithMemoizeOptions = createSelector( - (state: RootState) => state.todos, - // @ts-expect-error - todos => todos.map(t => t.id), - { argsMemoize: weakMapMemoize, argsMemoizeOptions: { maxSize: 2 } } - ) - // @ts-expect-error When argsMemoize is weakMapMemoize, type of argsMemoizeOptions needs to be the same as options args in weakMapMemoize. - const selectorWeakMapSeparateInlineArgsWithMemoizeOptions1 = createSelector( - [ - (state: RootState) => state.todos, - // @ts-expect-error - todos => todos.map(t => t.id) - ], - { - argsMemoize: weakMapMemoize, - argsMemoizeOptions: { maxSize: 2 } - } - ) - // @ts-expect-error When argsMemoize is weakMapMemoize, type of argsMemoizeOptions needs to be the same as options args in weakMapMemoize. - const selectorWeakMapSeparateInlineArgsWithMemoizeOptions2 = createSelector( - (state: RootState) => state.todos, - // @ts-expect-error - todos => todos.map(t => t.id), - { - memoize: lruMemoize, - argsMemoize: weakMapMemoize, - memoizeOptions: { - equalityCheck: - // @ts-expect-error - (a, b) => a === b, - maxSize: 2 - }, - argsMemoizeOptions: { maxSize: 2 } - } - ) - - const createSelectorLruMemoize = createSelectorCreator({ - memoize: lruMemoize - }) - const selectorWeakMapSeparateInlineArgsWithMemoizeOptions3 = - // @ts-expect-error When argsMemoize is weakMapMemoize, type of argsMemoizeOptions needs to be the same as options args in weakMapMemoize. - createSelectorLruMemoize( - (state: RootState) => state.todos, - // @ts-expect-error - todos => todos.map(t => t.id), - { - memoize: lruMemoize, - argsMemoize: weakMapMemoize, - // memoizeOptions: [], - memoizeOptions: [ - { - equalityCheck: - // @ts-expect-error - (a, b) => a === b, - maxSize: 2 - } - ], - argsMemoizeOptions: [{ maxSize: 2 }] - } - ) - - const selectorWeakMapSeparateInlineArgsWithMemoizeOptions5 = - // @ts-expect-error - createSelectorLruMemoize( - [(state: RootState) => state.todos], - // @ts-expect-error - todos => todos.map(t => t.id), - { - argsMemoize: weakMapMemoize, - memoizeOptions: [{ isPromise: false }], - argsMemoizeOptions: [] - } - ) - const selectorWeakMapSeparateInlineArgsWithMemoizeOptions6 = - createSelectorLruMemoize( - (state: RootState) => state.todos, - todos => todos.map(t => t.id), - { - argsMemoize: weakMapMemoize, - memoize: weakMapMemoize, - memoizeOptions: [], - argsMemoizeOptions: [] - // argsMemoizeOptions: (a, b) => a === b - } - ) - const createSelectorDefault = createSelectorCreator(lruMemoize) - const createSelectorWeakMap = createSelectorCreator(weakMapMemoize) - const createSelectorAutotrack = createSelectorCreator(autotrackMemoize) - const changeMemoizeMethodSelectorDefault = createSelectorDefault( - (state: RootState) => state.todos, - todos => todos.map(t => t.id), - { argsMemoize: weakMapMemoize } - ) - const changeMemoizeMethodSelectorWeakMap = createSelectorWeakMap( - (state: RootState) => state.todos, - todos => todos.map(t => t.id), - { argsMemoize: lruMemoize } - ) - const changeMemoizeMethodSelectorAutotrack = createSelectorAutotrack( - (state: RootState) => state.todos, - todos => todos.map(t => t.id), - { argsMemoize: lruMemoize } - ) - const changeMemoizeMethodSelectorDefaultWithMemoizeOptions = - // @ts-expect-error When argsMemoize is changed to weakMapMemoize or autotrackMemoize, argsMemoizeOptions cannot be the same type as options args in lruMemoize. - createSelectorDefault( - (state: RootState) => state.todos, - // @ts-expect-error - todos => todos.map(t => t.id), - { argsMemoize: weakMapMemoize, argsMemoizeOptions: { maxSize: 2 } } - ) - const changeMemoizeMethodSelectorWeakMapWithMemoizeOptions = - createSelectorWeakMap( - (state: RootState) => state.todos, - todos => todos.map(t => t.id), - { argsMemoize: lruMemoize, argsMemoizeOptions: { maxSize: 2 } } // When argsMemoize is changed to lruMemoize, argsMemoizeOptions can now be the same type as options args in lruMemoize. - ) - const changeMemoizeMethodSelectorAutotrackWithMemoizeOptions = - createSelectorAutotrack( - (state: RootState) => state.todos, - todos => todos.map(t => t.id), - { argsMemoize: lruMemoize, argsMemoizeOptions: { maxSize: 2 } } // When argsMemoize is changed to lruMemoize, argsMemoizeOptions can now be the same type as options args in lruMemoize. - ) -} - -function overrideMemoizeAndArgsMemoizeInCreateSelector() { - const createSelectorMicroMemoize = createSelectorCreator({ - memoize: microMemoize, - memoizeOptions: [{ isEqual: (a, b) => a === b }], - // memoizeOptions: { isEqual: (a, b) => a === b }, - argsMemoize: microMemoize, - argsMemoizeOptions: { isEqual: (a, b) => a === b } - }) - const selectorMicroMemoize = createSelectorMicroMemoize( - (state: RootState) => state.todos, - todos => todos.map(({ id }) => id) - ) - expectExactType(selectorMicroMemoize(state)) - // @ts-expect-error - selectorMicroMemoize() - // Checking existence of fields related to `argsMemoize` - selectorMicroMemoize.cache - selectorMicroMemoize.fn() - selectorMicroMemoize.isMemoized - selectorMicroMemoize.options - // @ts-expect-error - selectorMicroMemoize.clearCache() - // Checking existence of fields related to `memoize` - selectorMicroMemoize.memoizedResultFunc.cache - selectorMicroMemoize.memoizedResultFunc.fn() - selectorMicroMemoize.memoizedResultFunc.isMemoized - selectorMicroMemoize.memoizedResultFunc.options - // @ts-expect-error - selectorMicroMemoize.memoizedResultFunc.clearCache() - // Checking existence of fields related to the actual memoized selector - selectorMicroMemoize.dependencies - expectExactType< - [ - (state: RootState) => { - id: number - completed: boolean - }[] - ] - >(selectorMicroMemoize.dependencies) - expectExactType(selectorMicroMemoize.lastResult()) - // @ts-expect-error - selectorMicroMemoize.memoizedResultFunc() - expectExactType( - selectorMicroMemoize.memoizedResultFunc([{ id: 0, completed: true }]) - ) - selectorMicroMemoize.recomputations() - selectorMicroMemoize.resetRecomputations() - // @ts-expect-error - selectorMicroMemoize.resultFunc() - expectExactType( - selectorMicroMemoize.resultFunc([{ id: 0, completed: true }]) - ) - - // Checking to see if types dynamically change if memoize or argsMemoize are overridden inside `createSelector`. - // `microMemoize` was initially passed into `createSelectorCreator` - // as `memoize` and `argsMemoize`, After overriding them both to `lruMemoize`, - // not only does the type for `memoizeOptions` and `argsMemoizeOptions` change to - // the options parameter of `lruMemoize`, the output selector fields - // also change their type to the return type of `lruMemoize`. - const selectorMicroMemoizeOverridden = createSelectorMicroMemoize( - (state: RootState) => state.todos, - todos => todos.map(t => t.id), - { - memoize: lruMemoize, - argsMemoize: lruMemoize, - memoizeOptions: { equalityCheck: (a, b) => a === b, maxSize: 2 }, - argsMemoizeOptions: { equalityCheck: (a, b) => a === b, maxSize: 3 } - } - ) - expectExactType(selectorMicroMemoizeOverridden(state)) - // @ts-expect-error - selectorMicroMemoizeOverridden() - // Checking existence of fields related to `argsMemoize` - selectorMicroMemoizeOverridden.clearCache() // Prior to override, this field did NOT exist. - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverridden.cache - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverridden.fn() - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverridden.isMemoized - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverridden.options - // Checking existence of fields related to `memoize` - selectorMicroMemoizeOverridden.memoizedResultFunc.clearCache() // Prior to override, this field did NOT exist. - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverridden.memoizedResultFunc.cache - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverridden.memoizedResultFunc.fn() - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverridden.memoizedResultFunc.isMemoized - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverridden.memoizedResultFunc.options - // Checking existence of fields related to the actual memoized selector - expectExactType< - [ - (state: RootState) => { - id: number - completed: boolean - }[] - ] - >(selectorMicroMemoizeOverridden.dependencies) - expectExactType( - selectorMicroMemoizeOverridden.memoizedResultFunc([ - { id: 0, completed: true } - ]) - ) - // @ts-expect-error - selectorMicroMemoizeOverridden.memoizedResultFunc() - selectorMicroMemoizeOverridden.recomputations() - selectorMicroMemoizeOverridden.resetRecomputations() - // @ts-expect-error - selectorMicroMemoizeOverridden.resultFunc() - expectExactType( - selectorMicroMemoizeOverridden.resultFunc([{ id: 0, completed: true }]) - ) - // Making sure the type behavior is consistent when args are passed in as an array. - const selectorMicroMemoizeOverriddenArray = createSelectorMicroMemoize( - [(state: RootState) => state.todos], - todos => todos.map(({ id }) => id), - { - memoize: lruMemoize, - argsMemoize: lruMemoize, - memoizeOptions: { equalityCheck: (a, b) => a === b, maxSize: 2 }, - argsMemoizeOptions: { equalityCheck: (a, b) => a === b, maxSize: 3 } - } - ) - expectExactType(selectorMicroMemoizeOverriddenArray(state)) - // @ts-expect-error - selectorMicroMemoizeOverriddenArray() - // Checking existence of fields related to `argsMemoize` - selectorMicroMemoizeOverriddenArray.clearCache() // Prior to override, this field did NOT exist. - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverriddenArray.cache - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverriddenArray.fn() - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverriddenArray.isMemoized - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverriddenArray.options - // Checking existence of fields related to `memoize` - selectorMicroMemoizeOverriddenArray.memoizedResultFunc.clearCache() // Prior to override, this field did NOT exist. - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverriddenArray.memoizedResultFunc.cache - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverriddenArray.memoizedResultFunc.fn() - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverriddenArray.memoizedResultFunc.isMemoized - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverriddenArray.memoizedResultFunc.options - // Checking existence of fields related to the actual memoized selector - expectExactType< - [ - (state: RootState) => { - id: number - completed: boolean - }[] - ] - >(selectorMicroMemoizeOverriddenArray.dependencies) - expectExactType( - selectorMicroMemoizeOverriddenArray.memoizedResultFunc([ - { id: 0, completed: true } - ]) - ) - // @ts-expect-error - selectorMicroMemoizeOverriddenArray.memoizedResultFunc() - selectorMicroMemoizeOverriddenArray.recomputations() - selectorMicroMemoizeOverriddenArray.resetRecomputations() - // @ts-expect-error - selectorMicroMemoizeOverriddenArray.resultFunc() - expectExactType( - selectorMicroMemoizeOverriddenArray.resultFunc([{ id: 0, completed: true }]) - ) - const selectorMicroMemoizeOverrideArgsMemoizeOnlyWrong = - // @ts-expect-error Because `memoizeOptions` should not contain `resultEqualityCheck`. - createSelectorMicroMemoize( - (state: RootState) => state.todos, - todos => todos.map(({ id }) => id), - { - argsMemoize: lruMemoize, - memoizeOptions: { - isPromise: false, - resultEqualityCheck: - // @ts-expect-error - (a, b) => a === b - }, - argsMemoizeOptions: { resultEqualityCheck: (a, b) => a === b } - } - ) - const selectorMicroMemoizeOverrideArgsMemoizeOnly = - createSelectorMicroMemoize( - (state: RootState) => state.todos, - todos => todos.map(({ id }) => id), - { - argsMemoize: lruMemoize, - memoizeOptions: { isPromise: false }, - argsMemoizeOptions: { resultEqualityCheck: (a, b) => a === b } - } - ) - expectExactType(selectorMicroMemoizeOverrideArgsMemoizeOnly(state)) - // @ts-expect-error - selectorMicroMemoizeOverrideArgsMemoizeOnly() - // Checking existence of fields related to `argsMemoize` - selectorMicroMemoizeOverrideArgsMemoizeOnly.clearCache() // Prior to override, this field did NOT exist. - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverrideArgsMemoizeOnly.cache - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverrideArgsMemoizeOnly.fn() - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverrideArgsMemoizeOnly.isMemoized - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverrideArgsMemoizeOnly.options - - // Checking existence of fields related to `memoize`, these should still be the same. - selectorMicroMemoizeOverrideArgsMemoizeOnly.memoizedResultFunc.cache - selectorMicroMemoizeOverrideArgsMemoizeOnly.memoizedResultFunc.fn() - selectorMicroMemoizeOverrideArgsMemoizeOnly.memoizedResultFunc.isMemoized - selectorMicroMemoizeOverrideArgsMemoizeOnly.memoizedResultFunc.options - // @ts-expect-error Note that since we did not override `memoize` in the options object, - // `memoizedResultFunc.clearCache` is still an invalid field access. - selectorMicroMemoizeOverrideArgsMemoizeOnly.memoizedResultFunc.clearCache() - // Checking existence of fields related to the actual memoized selector - expectExactType< - [ - (state: RootState) => { - id: number - completed: boolean - }[] - ] - >(selectorMicroMemoizeOverrideArgsMemoizeOnly.dependencies) - expectExactType( - selectorMicroMemoizeOverrideArgsMemoizeOnly.lastResult() - ) - expectExactType( - selectorMicroMemoizeOverrideArgsMemoizeOnly.memoizedResultFunc([ - { id: 0, completed: true } - ]) - ) - // @ts-expect-error - selectorMicroMemoizeOverrideArgsMemoizeOnly.memoizedResultFunc() - selectorMicroMemoizeOverrideArgsMemoizeOnly.recomputations() - selectorMicroMemoizeOverrideArgsMemoizeOnly.resetRecomputations() - // @ts-expect-error - selectorMicroMemoizeOverrideArgsMemoizeOnly.resultFunc() - expectExactType( - selectorMicroMemoizeOverrideArgsMemoizeOnly.resultFunc([ - { id: 0, completed: true } - ]) - ) - - const selectorMicroMemoizeOverrideMemoizeOnly = createSelectorMicroMemoize( - (state: RootState) => state.todos, - todos => todos.map(t => t.id), - { - memoize: lruMemoize, - memoizeOptions: { resultEqualityCheck: (a, b) => a === b } - } - ) - expectExactType(selectorMicroMemoizeOverrideMemoizeOnly(state)) - // @ts-expect-error - selectorMicroMemoizeOverrideMemoizeOnly() - - // Checking existence of fields related to `argsMemoize` - selectorMicroMemoizeOverrideMemoizeOnly.cache - selectorMicroMemoizeOverrideMemoizeOnly.fn - selectorMicroMemoizeOverrideMemoizeOnly.isMemoized - selectorMicroMemoizeOverrideMemoizeOnly.options - // @ts-expect-error Note that since we did not override `argsMemoize` in the options object, - // `selector.clearCache` is still an invalid field access. - selectorMicroMemoizeOverrideMemoizeOnly.clearCache() - - // Checking existence of fields related to `memoize` - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverrideMemoizeOnly.memoizedResultFunc.cache - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverrideMemoizeOnly.memoizedResultFunc.fn() - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverrideMemoizeOnly.memoizedResultFunc.isMemoized - // @ts-expect-error Prior to override, this field DID exist. - selectorMicroMemoizeOverrideMemoizeOnly.memoizedResultFunc.options - selectorMicroMemoizeOverrideMemoizeOnly.memoizedResultFunc.clearCache() // Prior to override, this field did NOT exist. - - // Checking existence of fields related to the actual memoized selector - expectExactType< - [ - (state: RootState) => { - id: number - completed: boolean - }[] - ] - >(selectorMicroMemoizeOverrideMemoizeOnly.dependencies) - expectExactType( - selectorMicroMemoizeOverrideMemoizeOnly.lastResult() - ) - expectExactType( - selectorMicroMemoizeOverrideMemoizeOnly.memoizedResultFunc([ - { id: 0, completed: true } - ]) - ) - // @ts-expect-error - selectorMicroMemoizeOverrideMemoizeOnly.memoizedResultFunc() - selectorMicroMemoizeOverrideMemoizeOnly.recomputations() - selectorMicroMemoizeOverrideMemoizeOnly.resetRecomputations() - // @ts-expect-error - selectorMicroMemoizeOverrideMemoizeOnly.resultFunc() - expectExactType( - selectorMicroMemoizeOverrideMemoizeOnly.resultFunc([ - { id: 0, completed: true } - ]) - ) - - const selectorMicroMemoizePartiallyOverridden = - // @ts-expect-error Since `argsMemoize` is set to `lruMemoize`, `argsMemoizeOptions` must match the options object parameter of `lruMemoize` - createSelectorMicroMemoize( - (state: RootState) => state.todos, - // @ts-expect-error - todos => todos.map(t => t.id), - { - memoize: lruMemoize, - argsMemoize: lruMemoize, - memoizeOptions: { - equalityCheck: - // @ts-expect-error - (a, b) => a === b, - maxSize: 2 - }, - argsMemoizeOptions: { isPromise: false } // This field causes a type error since it does not match the options param of `lruMemoize`. - } - ) - const selectorMicroMemoizePartiallyOverridden1 = - // @ts-expect-error Since `argsMemoize` is set to `lruMemoize`, `argsMemoizeOptions` must match the options object parameter of `lruMemoize` - createSelectorMicroMemoize( - (state: RootState) => state.todos, - // @ts-expect-error - todos => todos.map(t => t.id), - { - memoize: lruMemoize, - argsMemoize: lruMemoize, - memoizeOptions: [ - { - equalityCheck: - // @ts-expect-error - (a, b) => a === b, - maxSize: 2 - } - ], - argsMemoizeOptions: [{ isPromise: false }] // This field causes a type error since it does not match the options param of `lruMemoize`. - } - ) - const selectorMicroMemoizePartiallyOverridden2 = createSelectorMicroMemoize( - (state: RootState) => state.todos, - todos => todos.map(t => t.id), - { - argsMemoizeOptions: [{ isPromise: false }] - } - ) - - const selectorDefaultParametric = createSelector( - (state: RootState, id: number) => id, - (state: RootState) => state.todos, - (id, todos) => todos.filter(todo => todo.id === id), - { - argsMemoize: microMemoize, - devModeChecks: { inputStabilityCheck: 'never' }, - memoize: memoizeOne, - argsMemoizeOptions: [], - memoizeOptions: [(a, b) => a === b] - } - ) - expectExactType< - { - id: number - completed: boolean - }[] - >(selectorDefaultParametric(state, 0)) - expectExactType< - { - id: number - completed: boolean - }[] - >(selectorDefaultParametric(state, 1)) - // @ts-expect-error - selectorDefaultParametric(state) - // @ts-expect-error - selectorDefaultParametric(1) - // @ts-expect-error - selectorDefaultParametric(state, '') - // @ts-expect-error - selectorDefaultParametric(state, 1, 1) - // Checking existence of fields related to `argsMemoize` - // Prior to override, this field did NOT exist. - selectorDefaultParametric.cache - // Prior to override, this field did NOT exist. - selectorDefaultParametric.fn - // Prior to override, this field did NOT exist. - selectorDefaultParametric.isMemoized - // Prior to override, this field did NOT exist. - selectorDefaultParametric.options - // @ts-expect-error Prior to override, this field DID exist. - selectorDefaultParametric.clearCache() - - // Checking existence of fields related to `memoize` - // @ts-expect-error Prior to override, this field DID exist. - selectorDefaultParametric.memoizedResultFunc.clearCache() - // Prior to override, this field did NOT exist. - selectorDefaultParametric.memoizedResultFunc.clear() - - // Checking existence of fields related to the actual memoized selector - expectExactType< - [ - (state: RootState, id: number) => number, - (state: RootState) => { id: number; completed: boolean }[] - ] - >(selectorDefaultParametric.dependencies) - expectExactType<{ id: number; completed: boolean }[]>( - selectorDefaultParametric.lastResult() - ) - expectExactType<{ id: number; completed: boolean }[]>( - selectorDefaultParametric.memoizedResultFunc(0, [ - { id: 0, completed: true } - ]) - ) - // @ts-expect-error - selectorDefaultParametric.memoizedResultFunc() - selectorDefaultParametric.recomputations() - selectorDefaultParametric.resetRecomputations() - // @ts-expect-error - selectorDefaultParametric.resultFunc() - expectExactType<{ id: number; completed: boolean }[]>( - selectorDefaultParametric.resultFunc(0, [{ id: 0, completed: true }]) - ) -} - -function memoizeAndArgsMemoizeInCreateSelectorCreator() { - // If we don't pass in `argsMemoize`, the type for `argsMemoizeOptions` - // falls back to the options parameter of `lruMemoize`. - const createSelectorArgsMemoizeOptionsFallbackToDefault = - createSelectorCreator({ - memoize: microMemoize, - memoizeOptions: [{ isPromise: false }], - argsMemoizeOptions: { resultEqualityCheck: (a, b) => a === b } - }) - const selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault = - createSelectorArgsMemoizeOptionsFallbackToDefault( - (state: RootState) => state.todos, - todos => todos.map(({ id }) => id) - ) - expectExactType( - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault(state) - ) - // @ts-expect-error - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault() - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.resultFunc - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.clearCache() - // @ts-expect-error - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.cache - // @ts-expect-error - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.fn - // @ts-expect-error - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.isMemoized - // @ts-expect-error - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.options - // Checking existence of fields related to `memoize` - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.memoizedResultFunc - .cache - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.memoizedResultFunc.fn() - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.memoizedResultFunc - .isMemoized - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.memoizedResultFunc - .options - // @ts-expect-error - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.memoizedResultFunc.clearCache() - // Checking existence of fields related to the actual memoized selector - expectExactType< - [ - (state: RootState) => { - id: number - completed: boolean - }[] - ] - >(selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.dependencies) - expectExactType( - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.lastResult() - ) - expectExactType( - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.memoizedResultFunc([ - { id: 0, completed: true } - ]) - ) - // @ts-expect-error - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.memoizedResultFunc() - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.recomputations() - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.resetRecomputations() - // @ts-expect-error - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.resultFunc() - expectExactType( - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.resultFunc([ - { id: 0, completed: true } - ]) - ) - expectExactType( - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.memoize - ) - expectExactType( - selectorMicroMemoizeArgsMemoizeOptionsFallbackToDefault.argsMemoize - ) - - const createSelectorWithWrongArgsMemoizeOptions = - // @ts-expect-error If we don't pass in `argsMemoize`, the type for `argsMemoizeOptions` falls back to the options parameter of `weakMapMemoize`. - createSelectorCreator({ - memoize: microMemoize, - memoizeOptions: { isEqual: (a, b) => a === b }, - argsMemoizeOptions: { - isEqual: - // @ts-expect-error implicit any - (a, b) => a === b - } - }) - - // When passing in an options object as the first argument, there should be no other arguments. - const createSelectorWrong = createSelectorCreator( - { - // @ts-expect-error - memoize: microMemoize, - // @ts-expect-error - memoizeOptions: { isEqual: (a, b) => a === b }, - // @ts-expect-error - argsMemoizeOptions: { equalityCheck: (a, b) => a === b } - }, - [] // This causes the error. - ) -} - -function deepNesting() { - type State = { foo: string } - const readOne = (state: State) => state.foo - - const selector0 = createSelector(readOne, one => one) - const selector1 = createSelector(selector0, s => s) - const selector2 = createSelector(selector1, s => s) - const selector3 = createSelector(selector2, s => s) - const selector4 = createSelector(selector3, s => s) - const selector5 = createSelector(selector4, s => s) - const selector6 = createSelector(selector5, s => s) - const selector7 = createSelector(selector6, s => s) - const selector8 = createSelector(selector7, s => s) - const selector9 = createSelector(selector8, s => s) - const selector10 = createSelector(selector9, s => s, { - memoize: microMemoize - }) - selector10.dependencies[0].dependencies[0].dependencies[0].dependencies[0] - .dependencies[0].dependencies[0].dependencies[0].dependencies[0] - .dependencies[0].dependencies[0].memoizedResultFunc.clearCache - const selector11 = createSelector(selector10, s => s) - const selector12 = createSelector(selector11, s => s) - const selector13 = createSelector(selector12, s => s) - const selector14 = createSelector(selector13, s => s) - const selector15 = createSelector(selector14, s => s) - const selector16 = createSelector(selector15, s => s) - const selector17 = createSelector(selector16, s => s) - const selector18 = createSelector(selector17, s => s) - const selector19 = createSelector(selector18, s => s) - const selector20 = createSelector(selector19, s => s) - selector20.dependencies[0].dependencies[0].dependencies[0].dependencies[0] - .dependencies[0].dependencies[0].dependencies[0].dependencies[0] - .dependencies[0].dependencies[0].memoizedResultFunc.cache - const selector21 = createSelector(selector20, s => s) - const selector22 = createSelector(selector21, s => s) - const selector23 = createSelector(selector22, s => s) - const selector24 = createSelector(selector23, s => s) - const selector25 = createSelector(selector24, s => s) - const selector26 = createSelector(selector25, s => s) - const selector27 = createSelector(selector26, s => s) - const selector28 = createSelector(selector27, s => s) - const selector29 = createSelector(selector28, s => s) - const selector30 = createSelector(selector29, s => s) - selector30.dependencies[0].dependencies[0].dependencies[0].dependencies[0] - .dependencies[0].dependencies[0].dependencies[0].dependencies[0] - .dependencies[0].dependencies[0].dependencies[0].dependencies[0] - .dependencies[0].dependencies[0].dependencies[0].dependencies[0] - .dependencies[0].dependencies[0].dependencies[0].dependencies[0] - .dependencies[0].dependencies[0].dependencies[0].dependencies[0] - .dependencies[0].dependencies[0].dependencies[0].dependencies[0] - .dependencies[0].dependencies[0].memoizedResultFunc.clearCache -} - -function deepNesting1() { - type State = { foo: string } - const readOne = (state: State) => state.foo - - const selector0 = createSelector(readOne, one => one) - const selector1 = createSelector([selector0], s => s) - const selector2 = createSelector([selector1], s => s) - const selector3 = createSelector([selector2], s => s) - const selector4 = createSelector([selector3], s => s) - const selector5 = createSelector([selector4], s => s) - const selector6 = createSelector([selector5], s => s) - const selector7 = createSelector([selector6], s => s) - const selector8 = createSelector([selector7], s => s) - const selector9 = createSelector([selector8], s => s) - const selector10 = createSelector([selector9], s => s) - const selector11 = createSelector([selector10], s => s) - const selector12 = createSelector([selector11], s => s) - const selector13 = createSelector([selector12], s => s) - const selector14 = createSelector([selector13], s => s) - const selector15 = createSelector([selector14], s => s) - const selector16 = createSelector([selector15], s => s) - const selector17 = createSelector([selector16], s => s) - const selector18 = createSelector([selector17], s => s) - const selector19 = createSelector([selector18], s => s) - const selector20 = createSelector([selector19], s => s) - const selector21 = createSelector([selector20], s => s) - const selector22 = createSelector([selector21], s => s) - const selector23 = createSelector([selector22], s => s) - const selector24 = createSelector([selector23], s => s) - const selector25 = createSelector([selector24], s => s) - const selector26 = createSelector([selector25], s => s) - const selector27 = createSelector([selector26], s => s) - const selector28 = createSelector([selector27], s => s) - const selector29 = createSelector([selector28], s => s) - const selector30 = createSelector([selector29], s => s) -} - -function deepNesting2() { - type State = { foo: string } - const readOne = (state: State) => state.foo - - const selector0 = createSelector(readOne, one => one) - const selector1 = createSelector(selector0, s => s, { - memoize: lruMemoize - }) - const selector2 = createSelector(selector1, s => s, { - memoize: lruMemoize - }) - const selector3 = createSelector(selector2, s => s, { - memoize: lruMemoize - }) - const selector4 = createSelector(selector3, s => s, { - memoize: lruMemoize - }) - const selector5 = createSelector(selector4, s => s, { - memoize: lruMemoize - }) - const selector6 = createSelector(selector5, s => s, { - memoize: lruMemoize - }) - const selector7 = createSelector(selector6, s => s, { - memoize: lruMemoize - }) - const selector8 = createSelector(selector7, s => s, { - memoize: lruMemoize - }) - const selector9 = createSelector(selector8, s => s, { - memoize: lruMemoize - }) - const selector10 = createSelector(selector9, s => s, { - memoize: lruMemoize - }) - const selector11 = createSelector(selector10, s => s, { - memoize: lruMemoize - }) - const selector12 = createSelector(selector11, s => s, { - memoize: lruMemoize - }) - const selector13 = createSelector(selector12, s => s, { - memoize: lruMemoize - }) - const selector14 = createSelector(selector13, s => s, { - memoize: lruMemoize - }) - const selector15 = createSelector(selector14, s => s, { - memoize: lruMemoize - }) - const selector16 = createSelector(selector15, s => s, { - memoize: lruMemoize - }) - const selector17 = createSelector(selector16, s => s, { - memoize: lruMemoize - }) - const selector18 = createSelector(selector17, s => s, { - memoize: lruMemoize - }) - const selector19 = createSelector(selector18, s => s, { - memoize: lruMemoize - }) - const selector20 = createSelector(selector19, s => s, { - memoize: lruMemoize - }) - const selector21 = createSelector(selector20, s => s, { - memoize: lruMemoize - }) - const selector22 = createSelector(selector21, s => s, { - memoize: lruMemoize - }) - const selector23 = createSelector(selector22, s => s, { - memoize: lruMemoize - }) - const selector24 = createSelector(selector23, s => s, { - memoize: lruMemoize - }) - const selector25 = createSelector(selector24, s => s, { - memoize: lruMemoize - }) - const selector26 = createSelector(selector25, s => s, { - memoize: lruMemoize - }) - const selector27 = createSelector(selector26, s => s, { - memoize: lruMemoize - }) - const selector28 = createSelector(selector27, s => s, { - memoize: lruMemoize - }) - const selector29 = createSelector(selector28, s => s, { - memoize: lruMemoize - }) -} - -function parameterLimit() { - const selector = createSelector( - (state: { testString: string }) => state.testString, - (state: { testNumber: number }) => state.testNumber, - (state: { testBoolean: boolean }) => state.testBoolean, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testNumber: number }) => state.testNumber, - (state: { testStringArray: string[] }) => state.testStringArray, - (state: { testString: string }) => state.testString, - (state: { testNumber: number }) => state.testNumber, - (state: { testBoolean: boolean }) => state.testBoolean, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testNumber: number }) => state.testNumber, - (state: { testStringArray: string[] }) => state.testStringArray, - (state: { testString: string }) => state.testString, - (state: { testNumber: number }) => state.testNumber, - (state: { testBoolean: boolean }) => state.testBoolean, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testNumber: number }) => state.testNumber, - (state: { testStringArray: string[] }) => state.testStringArray, - (state: { testString: string }) => state.testString, - (state: { testNumber: number }) => state.testNumber, - (state: { testBoolean: boolean }) => state.testBoolean, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testNumber: number }) => state.testNumber, - (state: { testStringArray: string[] }) => state.testStringArray, - ( - foo1: string, - foo2: number, - foo3: boolean, - foo4: string, - foo5: string, - foo6: string, - foo7: string, - foo8: number, - foo9: string[], - foo10: string, - foo11: number, - foo12: boolean, - foo13: string, - foo14: string, - foo15: string, - foo16: string, - foo17: number, - foo18: string[], - foo19: string, - foo20: number, - foo21: boolean, - foo22: string, - foo23: string, - foo24: string, - foo25: string, - foo26: number, - foo27: string[], - foo28: string, - foo29: number, - foo30: boolean, - foo31: string, - foo32: string, - foo33: string, - foo34: string, - foo35: number, - foo36: string[] - ) => { - return { - foo1, - foo2, - foo3, - foo4, - foo5, - foo6, - foo7, - foo8, - foo9, - foo10, - foo11, - foo12, - foo13, - foo14, - foo15, - foo16, - foo17, - foo18, - foo19, - foo20, - foo21, - foo22, - foo23, - foo24, - foo25, - foo26, - foo27, - foo28, - foo29, - foo30, - foo31, - foo32, - foo33, - foo34, - foo35, - foo36 - } - } - ) -} diff --git a/typescript_test/test.ts b/typescript_test/test.ts deleted file mode 100644 index 0795f2e70..000000000 --- a/typescript_test/test.ts +++ /dev/null @@ -1,1738 +0,0 @@ -/* eslint-disable no-use-before-define */ - -import { configureStore, createSlice } from '@reduxjs/toolkit' -import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' -import { groupBy, isEqual } from 'lodash' -import memoizeOne from 'memoize-one' -import microMemoize from 'micro-memoize' -import type { TypedUseSelectorHook } from 'react-redux' -import { useSelector } from 'react-redux' -import type { - GetStateFromSelectors, - Selector, - SelectorResultArray, - TypedStructuredSelectorCreator -} from 'reselect' -import { - createSelector, - createSelectorCreator, - createStructuredSelector, - lruMemoize, - referenceEqualityCheck -} from 'reselect' -import { expectExactType } from './typesTestUtils' - -type Exact = (() => T extends A ? 1 : 0) extends () => T extends B - ? 1 - : 0 - ? A extends B - ? B extends A - ? unknown - : never - : never - : never - -interface StateA { - a: number -} - -interface StateAB { - a: number - b: number -} - -interface StateSub { - sub: { - a: number - } -} - -// Test exporting -export const testExportBasic = createSelector( - (state: StateA) => state.a, - a => a -) - -// Test for exporting declaration of created selector creator -export const testExportStructured = createSelectorCreator( - lruMemoize, - (a, b) => typeof a === typeof b -) - -function testSelector() { - type State = { foo: string } - - const selector = createSelector( - (state: State) => state.foo, - foo => foo - ) - - const res = selector.resultFunc('test') - selector.recomputations() - selector.resetRecomputations() - - const foo: string = selector({ foo: 'bar' }) - - // @ts-expect-error - selector({ foo: 'bar' }, { prop: 'value' }) - - // @ts-expect-error - const num: number = selector({ foo: 'bar' }) - - // allows heterogeneous parameter type input selectors - createSelector( - (state: { foo: string }) => state.foo, - (state: { bar: number }) => state.bar, - (foo, bar) => 1 - ) - - const selectorWithUnions = createSelector( - (state: State, val: string | number) => state.foo, - (state: State, val: string | number) => val, - (foo, val) => val - ) -} - -function testNestedSelector() { - type State = { foo: string; bar: number; baz: boolean } - - const selector = createSelector( - createSelector( - (state: State) => state.foo, - (state: State) => state.bar, - (foo, bar) => ({ foo, bar }) - ), - (state: State) => state.baz, - ({ foo, bar }, baz) => { - const foo1: string = foo - // @ts-expect-error - const foo2: number = foo - - const bar1: number = bar - // @ts-expect-error - const bar2: string = bar - - const baz1: boolean = baz - // @ts-expect-error - const baz2: string = baz - } - ) -} - -function testSelectorAsCombiner() { - type SubState = { foo: string } - type State = { bar: SubState } - - const subSelector = createSelector( - (state: SubState) => state.foo, - foo => foo - ) - - const selector = createSelector((state: State) => state.bar, subSelector) - - // @ts-expect-error - selector({ foo: '' }) - - // @ts-expect-error - const n: number = selector({ bar: { foo: '' } }) - - const s: string = selector({ bar: { foo: '' } }) -} - -type Component

= (props: P) => any - -declare function connect( - selector: Selector -): (component: Component

) => Component

- -function testConnect() { - connect( - createSelector( - (state: { foo: string }) => state.foo, - foo => ({ foo }) - ) - )(props => { - // @ts-expect-error - props.bar - - const foo: string = props.foo - }) - - const selector2 = createSelector( - (state: { foo: string }) => state.foo, - (state: { baz: number }, props: { bar: number }) => props.bar, - (foo, bar) => ({ foo, baz: bar }) - ) - - const connected = connect(selector2)(props => { - const foo: string = props.foo - const bar: number = props.bar - const baz: number = props.baz - // @ts-expect-error - props.fizz - }) - - connected({ bar: 42 }) - - // @ts-expect-error - connected({ bar: 42, baz: 123 }) -} - -function testInvalidTypeInCombinator() { - // @ts-expect-error - createSelector( - (state: { foo: string }) => state.foo, - (foo: number) => foo - ) - - createSelector( - (state: { foo: string; bar: number; baz: boolean }) => state.foo, - (state: any) => state.bar, - (state: any) => state.baz, - // @ts-expect-error - (foo: string, bar: number, baz: boolean, fizz: string) => {} - ) - - // does not allow heterogeneous parameter type - // selectors when the combinator function is typed differently - // @ts-expect-error - createSelector( - (state: { testString: string }) => state.testString, - (state: { testNumber: number }) => state.testNumber, - (state: { testBoolean: boolean }) => state.testBoolean, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testNumber: string }) => state.testNumber, - (state: { testStringArray: string[] }) => state.testStringArray, - ( - foo1: string, - foo2: number, - foo3: boolean, - foo4: string, - foo5: string, - foo6: string, - foo7: string, - foo8: number, - foo9: string[] - ) => { - return { foo1, foo2, foo3, foo4, foo5, foo6, foo7, foo8, foo9 } - } - ) - - // does not allow a large array of heterogeneous parameter type - // selectors when the combinator function is typed differently - // @ts-expect-error - createSelector( - [ - (state: { testString: string }) => state.testString, - (state: { testNumber: number }) => state.testNumber, - (state: { testBoolean: boolean }) => state.testBoolean, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testNumber: string }) => state.testNumber, - (state: { testStringArray: string[] }) => state.testStringArray - ], - ( - foo1: string, - foo2: number, - foo3: boolean, - foo4: string, - foo5: string, - foo6: string, - foo7: string, - foo8: number, - foo9: string[] - ) => { - return { foo1, foo2, foo3, foo4, foo5, foo6, foo7, foo8, foo9 } - } - ) -} - -function testParametricSelector() { - type State = { foo: string } - type Props = { bar: number } - - // allows heterogeneous parameter type selectors - const selector1 = createSelector( - (state: { testString: string }) => state.testString, - (state: { testNumber: number }) => state.testNumber, - (state: { testBoolean: boolean }) => state.testBoolean, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testStringArray: string[] }) => state.testStringArray, - ( - foo1: string, - foo2: number, - foo3: boolean, - foo4: string, - foo5: string, - foo6: string, - foo7: string, - foo8: string, - foo9: string[] - ) => { - return { foo1, foo2, foo3, foo4, foo5, foo6, foo7, foo8, foo9 } - } - ) - - const res1 = selector1({ - testString: 'a', - testNumber: 42, - testBoolean: true, - testStringArray: ['b', 'c'] - }) - - const selector = createSelector( - (state: State) => state.foo, - (state: State, props: Props) => props.bar, - (foo, bar) => ({ foo, bar }) - ) - - // @ts-expect-error - selector({ foo: 'fizz' }) - // @ts-expect-error - selector({ foo: 'fizz' }, { bar: 'baz' }) - - const ret = selector({ foo: 'fizz' }, { bar: 42 }) - const foo: string = ret.foo - const bar: number = ret.bar - - const selector2 = createSelector( - (state: State) => state.foo, - (state: State) => state.foo, - (state: State) => state.foo, - (state: State) => state.foo, - (state: State) => state.foo, - (state: State, props: Props) => props.bar, - (foo1, foo2, foo3, foo4, foo5, bar) => ({ - foo1, - foo2, - foo3, - foo4, - foo5, - bar - }) - ) - - selector2({ foo: 'fizz' }, { bar: 42 }) - - const selector3 = createSelector( - (s: State) => s.foo, - (s: State, x: string) => x, - (s: State, y: number) => y, - (v, x) => { - return x + v - } - ) - - // @ts-expect-error - selector3({ foo: 'fizz' }, 42) - - const selector4 = createSelector( - (s: State, val: number) => s.foo, - (s: State, val: string | number) => val, - (foo, val) => { - return val - } - ) - - selector4({ foo: 'fizz' }, 42) -} - -function testArrayArgument() { - const selector = createSelector( - [ - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }, props: { bar: number }) => props.bar - ], - (foo1, foo2, bar) => ({ foo1, foo2, bar }) - ) - - const ret = selector({ foo: 'fizz' }, { bar: 42 }) - const foo1: string = ret.foo1 - const foo2: string = ret.foo2 - const bar: number = ret.bar - - // @ts-expect-error - createSelector([(state: { foo: string }) => state.foo]) - - // @ts-expect-error - createSelector( - [ - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo - ], - (foo: string, bar: number) => {} - ) - - createSelector( - [ - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo - ], - ( - foo1: string, - foo2: string, - foo3: string, - foo4: string, - foo5: string, - foo6: string, - foo7: string, - foo8: string, - foo9: string, - foo10: string - ) => {} - ) - - // @ts-expect-error - createSelector( - [ - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo - ], - (foo1, foo2, foo3, foo4, foo5, foo6, foo7, foo8: number, foo9, foo10) => {} - ) - - // @ts-expect-error - createSelector( - [ - (state: { foo: string }) => state.foo, - // @ts-expect-error - state => state.foo, - // @ts-expect-error - state => state.foo, - // @ts-expect-error - state => state.foo, - // @ts-expect-error - state => state.foo, - // @ts-expect-error - state => state.foo, - // @ts-expect-error - state => state.foo, - // @ts-expect-error - state => state.foo, - 1 - ], - // We expect an error here, but the error differs between TS versions - // @ts-ignore - (foo1, foo2, foo3, foo4, foo5, foo6, foo7, foo8, foo9) => {} - ) - - const selector2 = createSelector( - [ - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo - ], - ( - foo1: string, - foo2: string, - foo3: string, - foo4: string, - foo5: string, - foo6: string, - foo7: string, - foo8: string, - foo9: string - ) => { - return { foo1, foo2, foo3, foo4, foo5, foo6, foo7, foo8, foo9 } - } - ) - - { - const ret = selector2({ foo: 'fizz' }) - const foo1: string = ret.foo1 - const foo2: string = ret.foo2 - const foo3: string = ret.foo3 - const foo4: string = ret.foo4 - const foo5: string = ret.foo5 - const foo6: string = ret.foo6 - const foo7: string = ret.foo7 - const foo8: string = ret.foo8 - const foo9: string = ret.foo9 - // @ts-expect-error - ret.foo10 - } - - // @ts-expect-error - selector2({ foo: 'fizz' }, { bar: 42 }) - - const parametric = createSelector( - [ - (state: { foo: string }, props: { bar: number }) => props.bar, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo, - (state: { foo: string }) => state.foo - ], - ( - bar: number, - foo1: string, - foo2: string, - foo3: string, - foo4: string, - foo5: string, - foo6: string, - foo7: string, - foo8: string - ) => { - return { foo1, foo2, foo3, foo4, foo5, foo6, foo7, foo8, bar } - } - ) - - // allows a large array of heterogeneous parameter type selectors - const correctlyTypedArraySelector = createSelector( - [ - (state: { testString: string }) => state.testString, - (state: { testNumber: number }) => state.testNumber, - (state: { testBoolean: boolean }) => state.testBoolean, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testString: string }) => state.testString, - (state: { testStringArray: string[] }) => state.testStringArray - ], - ( - foo1: string, - foo2: number, - foo3: boolean, - foo4: string, - foo5: string, - foo6: string, - foo7: string, - foo8: string, - foo9: string[] - ) => { - return { foo1, foo2, foo3, foo4, foo5, foo6, foo7, foo8, foo9 } - } - ) - - // @ts-expect-error - parametric({ foo: 'fizz' }) - - { - const ret = parametric({ foo: 'fizz' }, { bar: 42 }) - const foo1: string = ret.foo1 - const foo2: string = ret.foo2 - const foo3: string = ret.foo3 - const foo4: string = ret.foo4 - const foo5: string = ret.foo5 - const foo6: string = ret.foo6 - const foo7: string = ret.foo7 - const foo8: string = ret.foo8 - const bar: number = ret.bar - // @ts-expect-error - ret.foo9 - } -} - -function testOptionalArgumentsConflicting() { - type State = { foo: string; bar: number; baz: boolean } - - const selector = createSelector( - (state: State) => state.baz, - (state: State, arg: string) => arg, - (state: State, arg: number) => arg, - baz => { - const baz1: boolean = baz - // @ts-expect-error - const baz2: number = baz - } - ) - - // @ts-expect-error the selector above has inconsistent conflicting arguments so usage should error - selector({} as State) - // @ts-expect-error - selector({} as State, 'string') - // @ts-expect-error - selector({} as State, 1) - - const selector2 = createSelector( - (state: State, prefix: any) => prefix + state.foo, - str => str - ) - - // @ts-expect-error here we require one argument which can be anything so error if there are no arguments - selector2({} as State) - // no error passing anything in - selector2({} as State, 'blach') - selector2({} as State, 1) - - // here the argument is optional so it should be possible to omit the argument or pass anything - const selector3 = createSelector( - (state: State, prefix?: any) => prefix + state.foo, - str => str - ) - - selector3({} as State) - selector3({} as State, 1) - selector3({} as State, 'blach') - - // https://github.com/reduxjs/reselect/issues/563 - const selector4 = createSelector( - (state: State, prefix: string, suffix: any) => - prefix + state.foo + String(suffix), - str => str - ) - - // @ts-expect-error - selector4({} as State) - // @ts-expect-error - selector4({} as State, 'blach') - selector4({} as State, 'blach', 4) - - // as above but a unknown 2nd argument - const selector5 = createSelector( - (state: State, prefix: string, suffix: unknown) => - prefix + state.foo + String(suffix), - str => str - ) - - // @ts-expect-error - selector5({} as State) - // @ts-expect-error - selector5({} as State, 'blach') - selector5({} as State, 'blach', 4) - - // This next section is now obsolete with the changes in TS 4.9 - // // @ts-expect-error It would be great to delete this, it is not correct. - // // Due to what must be a TS bug? if the default parameter is used, we lose the type for prefix - // // and it is impossible to type the selector without typing prefix - // const selector6 = createSelector( - // (state: State, prefix = '') => prefix + state.foo, - // (str: string) => str - // ) - - // // because the suppressed error above, selector6 has broken typings and doesn't allow a passed parameter - // selector6({} as State) - // // @ts-expect-error would be great if we can delete this, it should not error - // selector6({} as State, 'blach') - // // @ts-expect-error wrong type - // selector6({} as State, 1) - - // this is an example fixing selector6. We have to add a un-necessary typing in and magically the types are correct - const selector7 = createSelector( - ( - state: State, - // eslint-disable-next-line @typescript-eslint/no-inferrable-types - prefix: string = 'a' - ) => prefix + state.foo, - (str: string) => str - ) - - selector7({} as State) - selector7({} as State, 'blach') - // @ts-expect-error wrong type - selector7({} as State, 1) - - const selector8 = createSelector( - (state: State, prefix: unknown) => prefix, - str => str - ) - - // @ts-expect-error needs a argument - selector8({} as State) - // allowed to pass anything as the type is unknown - selector8({} as State, 'blach') - selector8({} as State, 2) -} - -function testLruMemoize() { - const func = (a: string) => +a - - const memoized = lruMemoize(func) - - const ret0: number = memoized('42') - // @ts-expect-error - const ret1: string = memoized('42') - - const memoized2 = lruMemoize( - (str: string, arr: string[]): { str: string; arr: string[] } => ({ - str, - arr - }), - (a: T, b: T) => { - return `${a}` === `${b}` - } - ) - - const ret2 = memoized2('', ['1', '2']) - const str: string = ret2.str - const arr: string[] = ret2.arr -} - -function testCreateSelectorCreator() { - const defaultCreateSelector = createSelectorCreator(lruMemoize) - - const selector = defaultCreateSelector( - (state: { foo: string }) => state.foo, - foo => foo - ) - const value: string = selector({ foo: 'fizz' }) - - // @ts-expect-error - selector({ foo: 'fizz' }, { bar: 42 }) - - // clearCache should exist because of lruMemoize - selector.clearCache() - - const parametric = defaultCreateSelector( - (state: { foo: string }) => state.foo, - (state: { foo: string }, props: { bar: number }) => props.bar, - (foo, bar) => ({ foo, bar }) - ) - - // @ts-expect-error - parametric({ foo: 'fizz' }) - - const ret = parametric({ foo: 'fizz' }, { bar: 42 }) - const foo: string = ret.foo - const bar: number = ret.bar - - // @ts-expect-error - createSelectorCreator(lruMemoize, 1) - - createSelectorCreator(lruMemoize, (a: T, b: T) => { - return `${a}` === `${b}` - }) -} - -function testCreateStructuredSelector() { - const oneParamSelector = createStructuredSelector({ - foo: (state: StateAB) => state.a, - bar: (state: StateAB) => state.b - }) - - const threeParamSelector = createStructuredSelector({ - foo: (state: StateAB, c: number, d: string) => state.a, - bar: (state: StateAB, c: number, d: string) => state.b - }) - - interface RootState { - foo: string - bar: number - } - - const typedStructuredSelectorCreator = - createStructuredSelector.withTypes() - - const selector = typedStructuredSelectorCreator({ - foo: state => state.foo, - bar: state => +state.foo - }) - - const res1 = selector({ foo: '42', bar: 1 }) - const foo: string = res1.foo - const bar: number = res1.bar - - // @ts-expect-error - selector({ bar: '42' }) - - // @ts-expect-error - selector({ foo: '42' }, { bar: 42 }) - - typedStructuredSelectorCreator({ - // @ts-expect-error - bar: (state: { baz: boolean }) => 1 - }) - - typedStructuredSelectorCreator({ - bar: state => state.foo - }) - - typedStructuredSelectorCreator({ - baz: state => state.foo - }) - - // Test automatic inference of types for createStructuredSelector via overload - type State = { foo: string } - const FooSelector = (state: State, a: number, b: string) => state.foo - const BarSelector = (state: State, a: number, b: string) => +state.foo - - const selector2 = createStructuredSelector({ - foo: FooSelector, - bar: BarSelector - }) - - const selectorGenerics = createStructuredSelector<{ - foo: typeof FooSelector - bar: typeof BarSelector - }>({ - foo: state => state.foo, - bar: state => +state.foo - }) - - type ExpectedResult = { - foo: string - bar: number - } - - const resOneParam = oneParamSelector({ a: 1, b: 2 }) - const resThreeParams = threeParamSelector({ a: 1, b: 2 }, 99, 'blah') - const res2: ExpectedResult = selector({ foo: '42', bar: 0 }) - const res3: ExpectedResult = selector2({ foo: '42' }, 99, 'test') - const resGenerics: ExpectedResult = selectorGenerics( - { foo: '42' }, - 99, - 'test' - ) - - //@ts-expect-error - selector2({ bar: '42' }) - // @ts-expect-error - selectorGenerics({ bar: '42' }) -} - -// TODO: Remove this function once `TypedStructuredSelectorCreator` is removed. -function testTypedCreateStructuredSelector() { - type RootState = { - foo: string - bar: number - } - - const selectFoo = (state: RootState) => state.foo - const selectBar = (state: RootState) => state.bar - - const typedStructuredSelectorCreator: TypedStructuredSelectorCreator = - createStructuredSelector - - typedStructuredSelectorCreator({ - foo: selectFoo, - bar: selectBar - }) - - // @ts-expect-error Because `bar` is missing. - typedStructuredSelectorCreator({ - foo: selectFoo - }) - - // This works - const selectorGenerics = createStructuredSelector<{ - foo: typeof selectFoo - bar: typeof selectBar - }>({ - foo: state => state.foo, - bar: state => +state.foo - }) - - // This also works - const selectorGenerics1 = typedStructuredSelectorCreator<{ - foo: typeof selectFoo - bar: typeof selectBar - }>({ - foo: state => state.foo, - bar: state => +state.foo - }) - - // Their types are the same. - expectExactType(selectorGenerics) -} - -function testDynamicArrayArgument() { - interface Elem { - val1: string - val2: string - } - const data: ReadonlyArray = [ - { val1: 'a', val2: 'aa' }, - { val1: 'b', val2: 'bb' } - ] - - createSelector( - data.map(obj => () => obj.val1), - (...vals) => vals.join(',') - ) - - createSelector( - data.map(obj => () => obj.val1), - // @ts-expect-error - vals => vals.join(',') - ) - - createSelector( - data.map(obj => () => obj.val1), - (...vals: string[]) => 0 - ) - // @ts-expect-error - createSelector( - data.map(obj => () => obj.val1), - (...vals: number[]) => 0 - ) - - const s = createSelector( - data.map(obj => (state: StateA, fld: keyof Elem) => obj[fld]), - (...vals) => vals.join(',') - ) - s({ a: 42 }, 'val1') - s({ a: 42 }, 'val2') - // @ts-expect-error - s({ a: 42 }, 'val3') -} - -function testStructuredSelectorTypeParams() { - type GlobalState = { - foo: string - bar: number - } - - const selectFoo = (state: GlobalState) => state.foo - const selectBar = (state: GlobalState) => state.bar - - // Output state should be the same as input, if not provided - // @ts-expect-error - createStructuredSelector({ - foo: selectFoo - // bar: selectBar, - // ^^^ because this is missing, an error is thrown - }) -} - -function multiArgMemoize any>( - func: F, - a: number, - b: string, - equalityCheck = referenceEqualityCheck -): F { - // @ts-ignore - return () => {} -} - -// #384: check for lruMemoize - -{ - interface Transaction { - transactionId: string - } - - const toId = (transaction: Transaction) => transaction.transactionId - const transactionsIds = (transactions: Transaction[]) => - transactions.map(toId) - const collectionsEqual = (ts1: Transaction[], ts2: Transaction[]) => - isEqual(transactionsIds(ts1), transactionsIds(ts2)) - - const createTransactionsSelector = createSelectorCreator( - lruMemoize, - collectionsEqual - ) - - const createMultiMemoizeArgSelector = createSelectorCreator( - multiArgMemoize, - 42, - 'abcd', - referenceEqualityCheck - ) - - const select = createMultiMemoizeArgSelector( - (state: { foo: string }) => state.foo, - foo => foo + '!' - ) - // error is not applicable anymore - select.clearCache() - - const createMultiMemoizeArgSelector2 = createSelectorCreator( - multiArgMemoize, - 42, - // @ts-expect-error - referenceEqualityCheck - ) - - const groupTransactionsByLabel = lruMemoize( - (transactions: Transaction[]) => - groupBy(transactions, item => item.transactionId), - collectionsEqual - ) -} - -// #445 -function issue445() { - interface TestState { - someNumber: number | null - someString: string | null - } - - interface Object1 { - str: string - } - interface Object2 { - num: number - } - - const getNumber = (state: TestState) => state.someNumber - const getString = (state: TestState) => state.someString - - function generateObject1(str: string): Object1 { - return { - str - } - } - function generateObject2(num: number): Object2 { - return { - num - } - } - function generateComplexObject( - num: number, - subObject: Object1, - subObject2: Object2 - ): boolean { - return true - } - - // ################ Tests ################ - - // Compact selector examples - - // Should error because generateObject1 can't take null - // @ts-expect-error - const getObject1 = createSelector([getString], generateObject1) - - // Should error because generateObject2 can't take null - // @ts-expect-error - const getObject2 = createSelector([getNumber], generateObject2) - - // Should error because mismatch of params - // @ts-expect-error - const getComplexObjectTest1 = createSelector( - [getObject1], - generateComplexObject - ) - - // Does error, but error is really weird and talks about "Object1 is not assignable to type number" - // @ts-expect-error - const getComplexObjectTest2 = createSelector( - [getNumber, getObject1], - generateComplexObject - ) - - // Should error because number can't be null - // @ts-expect-error - const getComplexObjectTest3 = createSelector( - [getNumber, getObject1, getObject2], - generateComplexObject - ) - - // Does error, but error is really weird and talks about "Object1 is not assignable to type number" - // @ts-expect-error - const getComplexObjectTest4 = createSelector( - [getObject1, getNumber, getObject2], - generateComplexObject - ) - - // Verbose selector examples - - // Errors correctly, says str can't be null - const getVerboseObject1 = createSelector([getString], str => - // @ts-expect-error - generateObject1(str) - ) - - // Errors correctly, says num can't be null - const getVerboseObject2 = createSelector([getNumber], num => - // @ts-expect-error - generateObject2(num) - ) - - // Errors correctly - const getVerboseComplexObjectTest1 = createSelector([getObject1], obj1 => - // @ts-expect-error - generateComplexObject(obj1) - ) - - // Errors correctly - const getVerboseComplexObjectTest2 = createSelector( - [getNumber, getObject1], - // @ts-expect-error - (num, obj1) => generateComplexObject(num, obj1) - ) - - // Errors correctly - const getVerboseComplexObjectTest3 = createSelector( - [getNumber, getObject1, getObject2], - // @ts-expect-error - (num, obj1, obj2) => generateComplexObject(num, obj1, obj2) - ) - - // Errors correctly - const getVerboseComplexObjectTest4 = createSelector( - [getObject1, getNumber, getObject2], - // @ts-expect-error - (num, obj1, obj2) => generateComplexObject(num, obj1, obj2) - ) -} - -// #492 -function issue492() { - const fooPropSelector = (_: {}, ownProps: { foo: string }) => ownProps.foo - const fooBarPropsSelector = ( - _: {}, - ownProps: { foo: string; bar: string } - ) => [ownProps.foo, ownProps.bar] - - const combinedSelector = createSelector( - fooPropSelector, - fooBarPropsSelector, - (foo, fooBar) => fooBar - ) -} - -function customMemoizationOptionTypes() { - const customMemoize = ( - f: (...args: any[]) => any, - a: string, - b: number, - c: boolean - ) => { - return f - } - - const customSelectorCreatorCustomMemoizeWorking = createSelectorCreator( - customMemoize, - 'a', - 42, - true - ) - - // @ts-expect-error - const customSelectorCreatorCustomMemoizeMissingArg = createSelectorCreator( - customMemoize, - 'a', - true - ) -} - -// createSelector config options -function createSelectorConfigOptions() { - const lruMemoizeAcceptsFirstArgDirectly = createSelector( - (state: StateAB) => state.a, - (state: StateAB) => state.b, - (a, b) => a + b, - { - memoize: lruMemoize, - memoizeOptions: (a, b) => a === b - } - ) - - const lruMemoizeAcceptsFirstArgAsObject = createSelector( - (state: StateAB) => state.a, - (state: StateAB) => state.b, - (a, b) => a + b, - { - memoize: lruMemoize, - memoizeOptions: { - equalityCheck: (a, b) => a === b - } - } - ) - - const lruMemoizeAcceptsArgsAsArray = createSelector( - (state: StateAB) => state.a, - (state: StateAB) => state.b, - (a, b) => a + b, - { - memoize: lruMemoize, - memoizeOptions: [(a, b) => a === b] - } - ) - - const customSelectorCreatorMicroMemoize = createSelectorCreator( - microMemoize, - { - maxSize: 42 - } - ) - - customSelectorCreatorMicroMemoize( - (state: StateAB) => state.a, - (state: StateAB) => state.b, - (a, b) => a + b, - { - memoizeOptions: [ - { - maxSize: 42 - } - ] - } - ) - - const customSelectorCreatorMemoizeOne = createSelectorCreator(memoizeOne) - - customSelectorCreatorMemoizeOne( - (state: StateAB) => state.a, - (state: StateAB) => state.b, - (a, b) => a + b, - { - memoizeOptions: (a, b) => a === b - } - ) -} - -// Verify more than 12 selectors are accepted -// Issue #525 -const withLotsOfInputSelectors = createSelector( - (_state: StateA) => 1, - (_state: StateA) => 2, - (_state: StateA) => 3, - (_state: StateA) => 4, - (_state: StateA) => 5, - (_state: StateA) => 6, - (_state: StateA) => 7, - (_state: StateA) => 8, - (_state: StateA) => 9, - (_state: StateA) => 10, - (_state: StateA) => 11, - (_state: StateA) => 12, - (_state: StateA) => 13, - (_state: StateA) => 14, - (_state: StateA) => 15, - (_state: StateA) => 16, - (_state: StateA) => 17, - (_state: StateA) => 18, - (_state: StateA) => 19, - (_state: StateA) => 20, - (_state: StateA) => 21, - (_state: StateA) => 22, - (_state: StateA) => 23, - (_state: StateA) => 24, - (_state: StateA) => 25, - (_state: StateA) => 26, - (_state: StateA) => 27, - (_state: StateA) => 28, - (...args) => args.length -) - -type SelectorArray29 = [ - (_state: StateA) => 1, - (_state: StateA) => 2, - (_state: StateA) => 3, - (_state: StateA) => 4, - (_state: StateA) => 5, - (_state: StateA) => 6, - (_state: StateA) => 7, - (_state: StateA) => 8, - (_state: StateA) => 9, - (_state: StateA) => 10, - (_state: StateA) => 11, - (_state: StateA) => 12, - (_state: StateA) => 13, - (_state: StateA) => 14, - (_state: StateA) => 15, - (_state: StateA) => 16, - (_state: StateA) => 17, - (_state: StateA) => 18, - (_state: StateA) => 19, - (_state: StateA) => 20, - (_state: StateA) => 21, - (_state: StateA) => 22, - (_state: StateA) => 23, - (_state: StateA) => 24, - (_state: StateA) => 25, - (_state: StateA) => 26, - (_state: StateA) => 27, - (_state: StateA) => 28, - (_state: StateA) => 29 -] - -type Results = SelectorResultArray -type State = GetStateFromSelectors - -// Ensure that input functions with mismatched states raise errors -{ - const input1 = (state: string) => 1 - const input2 = (state: number) => 2 - - const selector = createSelector(input1, input2, (...args) => 0) - // @ts-expect-error - selector('foo') - // @ts-expect-error - selector(5) -} -{ - const selector = createSelector( - (state: { foo: string }) => 1, - (state: { bar: string }) => 2, - (...args) => 0 - ) - selector({ foo: '', bar: '' }) - // @ts-expect-error - selector({ foo: '' }) - // @ts-expect-error - selector({ bar: '' }) -} - -{ - const selector = createSelector( - (state: { foo: string }) => 1, - (state: { foo: string }) => 2, - (...args) => 0 - ) - // @ts-expect-error - selector({ foo: '', bar: '' }) - selector({ foo: '' }) - // @ts-expect-error - selector({ bar: '' }) -} - -// Issue #526 -function testInputSelectorWithUndefinedReturn() { - type Input = { field: number | undefined } - type Output = string - type SelectorType = (input: Input) => Output - - const input = ({ field }: Input) => field - const result = (out: number | undefined): Output => 'test' - - // Make sure the selector type is honored - const selector: SelectorType = createSelector( - ({ field }: Input) => field, - args => 'test' - ) - - // even when memoizeOptions are passed - const selector2: SelectorType = createSelector( - ({ field }: Input) => field, - args => 'test', - { - memoize: lruMemoize, - memoizeOptions: { maxSize: 42 } - } - ) - - // Make sure inference of functions works... - const selector3: SelectorType = createSelector(input, result) - const selector4: SelectorType = createSelector(input, result, { - memoize: lruMemoize, - memoizeOptions: { maxSize: 42 } - }) -} - -function deepNesting() { - type State = { foo: string } - const readOne = (state: State) => state.foo - - const selector0 = createSelector(readOne, one => one) - const selector1 = createSelector(selector0, s => s) - const selector2 = createSelector(selector1, s => s) - const selector3 = createSelector(selector2, s => s) - const selector4 = createSelector(selector3, s => s) - const selector5 = createSelector(selector4, s => s) - const selector6 = createSelector(selector5, s => s) - const selector7 = createSelector(selector6, s => s) - const selector8 = createSelector(selector7, s => s) - const selector9 = createSelector(selector8, s => s) - const selector10 = createSelector(selector9, s => s) - const selector11 = createSelector(selector10, s => s) - const selector12 = createSelector(selector11, s => s) - const selector13 = createSelector(selector12, s => s) - const selector14 = createSelector(selector13, s => s) - const selector15 = createSelector(selector14, s => s) - const selector16 = createSelector(selector15, s => s) - const selector17 = createSelector(selector16, s => s) - const selector18 = createSelector(selector17, s => s) - const selector19 = createSelector(selector18, s => s) - const selector20 = createSelector(selector19, s => s) - const selector21 = createSelector(selector20, s => s) - const selector22 = createSelector(selector21, s => s) - const selector23 = createSelector(selector22, s => s) - const selector24 = createSelector(selector23, s => s) - const selector25 = createSelector(selector24, s => s) - const selector26 = createSelector(selector25, s => s) - const selector27 = createSelector(selector26, s => s) - const selector28 = createSelector(selector27, s => s) - const selector29 = createSelector(selector28, s => s) -} - -function issue540() { - const input1 = ( - _: StateA, - { testNumber }: { testNumber: number }, - c: number, - d: string - ) => testNumber - - const input2 = ( - _: StateA, - { testString }: { testString: string }, - c: number | string - ) => testString - - const input3 = ( - _: StateA, - { testBoolean }: { testBoolean: boolean }, - c: number | string, - d: string - ) => testBoolean - - const input4 = (_: StateA, { testString2 }: { testString2: string }) => - testString2 - - const testSelector = createSelector( - input1, - input2, - input3, - input4, - (testNumber, testString, testBoolean) => testNumber + testString - ) - - const state: StateA = { a: 42 } - const test = testSelector( - state, - { testNumber: 1, testString: '10', testBoolean: true, testString2: 'blah' }, - 42, - 'blah' - ) - - // #541 - const selectProp1 = createSelector( - [ - (state: StateA) => state, - (state: StateA, props: { prop1: number }) => props - ], - (state, { prop1 }) => [state, prop1] - ) - - const selectProp2 = createSelector( - [selectProp1, (state, props: { prop2: number }) => props], - (state, { prop2 }) => [state, prop2] - ) - - selectProp1({ a: 42 }, { prop1: 1 }) - // @ts-expect-error - selectProp2({ a: 42 }, { prop2: 2 }) -} - -function issue548() { - interface State { - value: Record | null - loading: boolean - } - - interface Props { - currency: string - } - - const isLoading = createSelector( - (state: State) => state, - (_: State, props: Props) => props.currency, - ({ loading }, currency) => loading - ) - - const mapData = createStructuredSelector({ - isLoading, - test2: (state: State) => 42 - }) - - const result = mapData({ value: null, loading: false }, { currency: 'EUR' }) -} - -function issue550() { - const some = createSelector( - (a: number) => a, - (_a: number, b: number) => b, - (a, b) => a + b - ) - - const test = some(1, 2) -} - -function rtkIssue1750() { - const slice = createSlice({ - name: 'test', - initialState: 0, - reducers: {} - }) - - interface Pokemon { - name: string - } - - // Define a service using a base URL and expected endpoints - const pokemonApi = createApi({ - reducerPath: 'pokemonApi', - baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }), - endpoints: builder => ({ - getPokemonByName: builder.query({ - query: name => `pokemon/${name}` - }) - }) - }) - - const store = configureStore({ - reducer: { - test: slice.reducer, - [pokemonApi.reducerPath]: pokemonApi.reducer - }, - middleware: getDefaultMiddleware => - getDefaultMiddleware().concat(pokemonApi.middleware) - }) - - type RootState = ReturnType - - const selectTest = createSelector( - (state: RootState) => state.test, - test => test - ) - - const useAppSelector: TypedUseSelectorHook = useSelector - - // Selector usage should compile correctly - const testItem = selectTest(store.getState()) - - function App() { - const test = useAppSelector(selectTest) - return null - } -} - -function handleNestedIncompatTypes() { - // Incompatible parameters should force errors even for nested fields. - // One-level-deep fields get stripped to empty objects, so they - // should be replaced with `never`. - // Deeper fields should get caught by TS. - // Playground: https://tsplay.dev/wg6X0W - const input1a = (_: StateA, param: { b: number }) => param.b - - const input1b = (_: StateA, param: { b: string }) => param.b - - const testSelector1 = createSelector(input1a, input1b, () => ({})) - - // @ts-expect-error - testSelector1({ a: 42 }, { b: 99 }) // should not compile - - const input2a = (_: StateA, param: { b: { c: number } }) => param.b.c - const input2b = (_: StateA, param: { b: { c: string } }) => param.b.c - - const testSelector2 = createSelector(input2a, input2b, (c1, c2) => {}) - - // @ts-expect-error - testSelector2({ a: 42 }, { b: { c: 99 } }) -} - -function issue554a() { - interface State { - foo: string - bar: number - } - - const initialState: State = { - foo: 'This is Foo', - bar: 1 - } - - const getFoo = (state: State) => { - return state.foo - } - getFoo(initialState) - - const getBar = (state: State) => { - return state.bar - } - getBar(initialState) - - const simple = createSelector(getFoo, getBar, (foo, bar) => { - return `${foo} => ${bar}` - }) - simple(initialState) - - // Input selectors with positional args - const firstInput = (_: State, first: string) => first - // Skip the first arg and return only the second. - const secondInput = (_: State, _first: string, second: number) => second - - const complexOne = createSelector( - getFoo, - getBar, - firstInput, - (foo, bar, first) => { - return `${foo} => ${bar} || ${first}` - } - ) - complexOne(initialState, 'first') - - const complexTwo = createSelector( - getFoo, - getBar, - firstInput, - secondInput, - (foo, bar, first, second) => { - return `${foo} => ${bar} || ${first} and ${second}` - } - ) - // TS should complain since 'second' should be `number` - // @ts-expect-error - complexTwo(initialState, 'first', 'second') -} - -function issue554b() { - interface State { - counter1: number - counter2: number - } - - const selectTest = createSelector( - (state: State, numberA?: number) => numberA, - (state: State) => state.counter2, - (numberA, counter2) => (numberA ? numberA + counter2 : counter2) - ) - - type selectTestParams = Parameters - const p1: selectTestParams = [{ counter1: 1, counter2: 2 }, 42] - expectExactType<[State, number?]>(p1) - - const result = selectTest({ counter1: 1, counter2: 2 }, 42) -} - -function issue554c() { - interface State { - counter1: number - counter2: number - } - - const selectTest = createSelector( - (state: State, numberA?: number) => numberA, // `numberA` is optional - (state: State) => state.counter2, - (numberA, counter2) => (numberA ? numberA + counter2 : counter2) - ) - - // @ts-expect-error - const value = selectTest({ counter1: 0, counter2: 0 }, 'what?') - - const selectTest2 = createSelector( - (state: State, numberA: number) => numberA, // `numberA` is not optional anymore - (state: State) => state.counter2, - (numberA, counter2) => (numberA ? numberA + counter2 : counter2) - ) - - // @ts-expect-error - const value2 = selectTest2({ counter1: 0, counter2: 0 }, 'what?') -} - -function issue555() { - type IReduxState = { - ui: { - x: string - y: string - } - } - - const someSelector1 = createSelector( - (state: IReduxState, param: 'x' | 'y' | undefined) => - param !== undefined ? state.ui[param] : null, - (a: string | null) => a - ) - - const someSelector2 = createSelector( - (state: IReduxState, param?: 'x' | 'y') => - param !== undefined ? state.ui[param] : null, - (a: string | null) => a - ) - - const someSelector3 = createSelector( - (state: IReduxState, param: 'x' | 'y' | null) => - param !== null ? state.ui[param] : null, - (a: string | null) => a - ) - - const state = { ui: { x: '1', y: '2' } } - - const selectorResult1 = someSelector1(state, undefined) - const selectorResult2 = someSelector2(state, undefined) - const selectorResult3 = someSelector3(state, null) -} - -function testCreateStructuredSelectorNew() { - interface State { - todos: { - id: number - completed: boolean - }[] - } - const state: State = { - todos: [ - { id: 0, completed: false }, - { id: 1, completed: false } - ] - } - - const selectorDefaultParametric = createSelector( - (state: State, id: number) => id, - (state: State) => state.todos, - (id, todos) => todos.filter(todo => todo.id === id) - ) - const multiArgsStructuredSelector = createStructuredSelector( - { - selectedTodos: (state: State) => state.todos, - selectedTodoById: (state: State, id: number) => state.todos[id], - selectedCompletedTodos: ( - state: State, - id: number, - isCompleted: boolean - ) => state.todos.filter(({ completed }) => completed === isCompleted) - }, - createSelectorCreator({ memoize: microMemoize, argsMemoize: microMemoize }) - ) - - multiArgsStructuredSelector.resultFunc( - [{ id: 2, completed: true }], - { id: 0, completed: false }, - [{ id: 0, completed: false }] - ).selectedCompletedTodos - - multiArgsStructuredSelector.memoizedResultFunc( - [{ id: 2, completed: true }], - { id: 0, completed: false }, - [{ id: 0, completed: false }] - ).selectedCompletedTodos - - multiArgsStructuredSelector.memoizedResultFunc.cache - multiArgsStructuredSelector.memoizedResultFunc.fn - multiArgsStructuredSelector.memoizedResultFunc.isMemoized - multiArgsStructuredSelector.memoizedResultFunc.options - - multiArgsStructuredSelector(state, 2, true).selectedCompletedTodos - expectExactType(multiArgsStructuredSelector.argsMemoize) - expectExactType(multiArgsStructuredSelector.memoize) - expectExactType< - [ - (state: State) => State['todos'], - (state: State, id: number) => State['todos'][number], - (state: State, id: number, isCompleted: boolean) => State['todos'] - ] - >(multiArgsStructuredSelector.dependencies) - // @ts-expect-error Wrong number of arguments. - multiArgsStructuredSelector(state, 2) -} diff --git a/typescript_test/tsconfig.json b/typescript_test/tsconfig.json deleted file mode 100644 index 81026e74a..000000000 --- a/typescript_test/tsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs", - "strict": true, - "target": "ES2015", - "lib": ["ES2021.WeakRef"], - "declaration": true, - "noEmit": true, - "skipLibCheck": true, - "paths": { - "reselect": ["../src/index"], // @remap-prod-remove-line - "@internal/*": ["../src/*"] - } - }, - "include": ["test.ts", "argsMemoize.typetest.ts"] -} diff --git a/typescript_test/typesTestUtils.ts b/typescript_test/typesTestUtils.ts deleted file mode 100644 index f0ca45a20..000000000 --- a/typescript_test/typesTestUtils.ts +++ /dev/null @@ -1,29 +0,0 @@ -export function expectType(t: T): T { - return t -} - -export declare type IsAny = true | false extends ( - T extends never ? true : false -) - ? True - : False - -export declare type IsUnknown = unknown extends T - ? IsAny - : False - -type Equals = IsAny< - T, - never, - IsAny -> - -export type IsEqual = (() => G extends A ? 1 : 2) extends < - G ->() => G extends B ? 1 : 2 - ? true - : false - -export function expectExactType(t: T) { - return (u: U & Equals) => {} -} diff --git a/vitest.config.mts b/vitest.config.mts index b45318ec5..7b527ac63 100644 --- a/vitest.config.mts +++ b/vitest.config.mts @@ -1,23 +1,19 @@ import { defineConfig } from 'vitest/config' -import path from 'node:path' -import { fileURLToPath } from 'node:url' - -// No __dirname under Node ESM -const __filename = fileURLToPath(import.meta.url) -const __dirname = path.dirname(__filename) - export default defineConfig({ test: { - typecheck: { tsconfig: 'type-tests/tsconfig.json' }, + pool: 'threads', + watch: false, globals: true, - include: ['./test/**/*.(spec|test).[jt]s?(x)'], - setupFiles: ['test/setup.vitest.ts'], + setupFiles: ['test/setup.ts'], alias: { - reselect: path.join(__dirname, 'src/index.ts'), // @remap-prod-remove-line + reselect: new URL( + process.env.TEST_DIST ? 'node_modules/reselect' : 'src/index.ts', + import.meta.url + ).pathname, // this mapping is disabled as we want `dist` imports in the tests only to be used for "type-only" imports which don't play a role for jest - '@internal': path.join(__dirname, 'src') + '@internal': new URL('src', import.meta.url).pathname } } }) diff --git a/yarn.lock b/yarn.lock index 56f2111ff..ba5b24f0f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17,226 +17,376 @@ __metadata: linkType: hard "@babel/code-frame@npm:^7.10.4": - version: 7.24.7 - resolution: "@babel/code-frame@npm:7.24.7" + version: 7.26.2 + resolution: "@babel/code-frame@npm:7.26.2" dependencies: - "@babel/highlight": "npm:^7.24.7" + "@babel/helper-validator-identifier": "npm:^7.25.9" + js-tokens: "npm:^4.0.0" picocolors: "npm:^1.0.0" - checksum: 10/4812e94885ba7e3213d49583a155fdffb05292330f0a9b2c41b49288da70cf3c746a3fda0bf1074041a6d741c33f8d7be24be5e96f41ef77395eeddc5c9ff624 + checksum: 10/db2c2122af79d31ca916755331bb4bac96feb2b334cdaca5097a6b467fdd41963b89b14b6836a14f083de7ff887fc78fa1b3c10b14e743d33e12dbfe5ee3d223 languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-validator-identifier@npm:7.24.7" - checksum: 10/86875063f57361471b531dbc2ea10bbf5406e12b06d249b03827d361db4cad2388c6f00936bcd9dc86479f7e2c69ea21412c2228d4b3672588b754b70a449d4b +"@babel/helper-validator-identifier@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-validator-identifier@npm:7.25.9" + checksum: 10/3f9b649be0c2fd457fa1957b694b4e69532a668866b8a0d81eabfa34ba16dbf3107b39e0e7144c55c3c652bf773ec816af8df4a61273a2bb4eb3145ca9cf478e languageName: node linkType: hard -"@babel/highlight@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/highlight@npm:7.24.7" +"@babel/runtime@npm:^7.12.5": + version: 7.26.0 + resolution: "@babel/runtime@npm:7.26.0" dependencies: - "@babel/helper-validator-identifier": "npm:^7.24.7" - chalk: "npm:^2.4.2" - js-tokens: "npm:^4.0.0" - picocolors: "npm:^1.0.0" - checksum: 10/69b73f38cdd4f881b09b939a711e76646da34f4834f4ce141d7a49a6bb1926eab1c594148970a8aa9360398dff800f63aade4e81fafdd7c8d8a8489ea93bfec1 + regenerator-runtime: "npm:^0.14.0" + checksum: 10/9f4ea1c1d566c497c052d505587554e782e021e6ccd302c2ad7ae8291c8e16e3f19d4a7726fb64469e057779ea2081c28b7dbefec6d813a22f08a35712c0f699 languageName: node linkType: hard -"@babel/runtime@npm:^7.12.5": - version: 7.25.6 - resolution: "@babel/runtime@npm:7.25.6" - dependencies: - regenerator-runtime: "npm:^0.14.0" - checksum: 10/0c4134734deb20e1005ffb9165bf342e1074576621b246d8e5e41cc7cb315a885b7d98950fbf5c63619a2990a56ae82f444d35fe8c4691a0b70c2fe5673667dc +"@esbuild/aix-ppc64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/aix-ppc64@npm:0.21.5" + conditions: os=aix & cpu=ppc64 languageName: node linkType: hard -"@esbuild/aix-ppc64@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/aix-ppc64@npm:0.23.0" +"@esbuild/aix-ppc64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/aix-ppc64@npm:0.24.0" conditions: os=aix & cpu=ppc64 languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/android-arm64@npm:0.23.0" +"@esbuild/android-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-arm64@npm:0.21.5" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@esbuild/android-arm@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/android-arm@npm:0.23.0" +"@esbuild/android-arm64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/android-arm64@npm:0.24.0" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/android-arm@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-arm@npm:0.21.5" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@esbuild/android-arm@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/android-arm@npm:0.24.0" conditions: os=android & cpu=arm languageName: node linkType: hard -"@esbuild/android-x64@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/android-x64@npm:0.23.0" +"@esbuild/android-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-x64@npm:0.21.5" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/android-x64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/android-x64@npm:0.24.0" conditions: os=android & cpu=x64 languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/darwin-arm64@npm:0.23.0" +"@esbuild/darwin-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/darwin-arm64@npm:0.21.5" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/darwin-x64@npm:0.23.0" +"@esbuild/darwin-arm64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/darwin-arm64@npm:0.24.0" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/darwin-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/darwin-x64@npm:0.21.5" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/freebsd-arm64@npm:0.23.0" +"@esbuild/darwin-x64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/darwin-x64@npm:0.24.0" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/freebsd-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/freebsd-arm64@npm:0.21.5" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/freebsd-arm64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/freebsd-arm64@npm:0.24.0" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/freebsd-x64@npm:0.23.0" +"@esbuild/freebsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/freebsd-x64@npm:0.21.5" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/freebsd-x64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/freebsd-x64@npm:0.24.0" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/linux-arm64@npm:0.23.0" +"@esbuild/linux-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-arm64@npm:0.21.5" conditions: os=linux & cpu=arm64 languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/linux-arm@npm:0.23.0" +"@esbuild/linux-arm64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/linux-arm64@npm:0.24.0" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/linux-arm@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-arm@npm:0.21.5" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@esbuild/linux-arm@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/linux-arm@npm:0.24.0" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/linux-ia32@npm:0.23.0" +"@esbuild/linux-ia32@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-ia32@npm:0.21.5" conditions: os=linux & cpu=ia32 languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/linux-loong64@npm:0.23.0" +"@esbuild/linux-ia32@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/linux-ia32@npm:0.24.0" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + +"@esbuild/linux-loong64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-loong64@npm:0.21.5" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + +"@esbuild/linux-loong64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/linux-loong64@npm:0.24.0" conditions: os=linux & cpu=loong64 languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/linux-mips64el@npm:0.23.0" +"@esbuild/linux-mips64el@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-mips64el@npm:0.21.5" conditions: os=linux & cpu=mips64el languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/linux-ppc64@npm:0.23.0" +"@esbuild/linux-mips64el@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/linux-mips64el@npm:0.24.0" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + +"@esbuild/linux-ppc64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-ppc64@npm:0.21.5" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/linux-riscv64@npm:0.23.0" +"@esbuild/linux-ppc64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/linux-ppc64@npm:0.24.0" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + +"@esbuild/linux-riscv64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-riscv64@npm:0.21.5" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + +"@esbuild/linux-riscv64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/linux-riscv64@npm:0.24.0" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/linux-s390x@npm:0.23.0" +"@esbuild/linux-s390x@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-s390x@npm:0.21.5" conditions: os=linux & cpu=s390x languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/linux-x64@npm:0.23.0" +"@esbuild/linux-s390x@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/linux-s390x@npm:0.24.0" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + +"@esbuild/linux-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-x64@npm:0.21.5" conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/netbsd-x64@npm:0.23.0" +"@esbuild/linux-x64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/linux-x64@npm:0.24.0" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/netbsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/netbsd-x64@npm:0.21.5" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/netbsd-x64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/netbsd-x64@npm:0.24.0" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openbsd-arm64@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/openbsd-arm64@npm:0.23.0" +"@esbuild/openbsd-arm64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/openbsd-arm64@npm:0.24.0" conditions: os=openbsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/openbsd-x64@npm:0.23.0" +"@esbuild/openbsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/openbsd-x64@npm:0.21.5" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/openbsd-x64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/openbsd-x64@npm:0.24.0" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/sunos-x64@npm:0.23.0" +"@esbuild/sunos-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/sunos-x64@npm:0.21.5" conditions: os=sunos & cpu=x64 languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/win32-arm64@npm:0.23.0" +"@esbuild/sunos-x64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/sunos-x64@npm:0.24.0" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/win32-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-arm64@npm:0.21.5" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/win32-ia32@npm:0.23.0" +"@esbuild/win32-arm64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/win32-arm64@npm:0.24.0" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/win32-ia32@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-ia32@npm:0.21.5" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.23.0": - version: 0.23.0 - resolution: "@esbuild/win32-x64@npm:0.23.0" +"@esbuild/win32-ia32@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/win32-ia32@npm:0.24.0" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@esbuild/win32-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-x64@npm:0.21.5" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/win32-x64@npm:0.24.0": + version: 0.24.0 + resolution: "@esbuild/win32-x64@npm:0.24.0" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": - version: 4.4.0 - resolution: "@eslint-community/eslint-utils@npm:4.4.0" + version: 4.4.1 + resolution: "@eslint-community/eslint-utils@npm:4.4.1" dependencies: - eslint-visitor-keys: "npm:^3.3.0" + eslint-visitor-keys: "npm:^3.4.3" peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - checksum: 10/8d70bcdcd8cd279049183aca747d6c2ed7092a5cf0cf5916faac1ef37ffa74f0c245c2a3a3d3b9979d9dfdd4ca59257b4c5621db699d637b847a2c5e02f491c2 + checksum: 10/ae92a11412674329b4bd38422518601ec9ceae28e251104d1cad83715da9d38e321f68c817c39b64e66d0af7d98df6f9a10ad2dc638911254b47fb8932df00ef languageName: node linkType: hard "@eslint-community/regexpp@npm:^4.5.1, @eslint-community/regexpp@npm:^4.6.1": - version: 4.11.0 - resolution: "@eslint-community/regexpp@npm:4.11.0" - checksum: 10/f053f371c281ba173fe6ee16dbc4fe544c84870d58035ccca08dba7f6ce1830d895ce3237a0db89ba37616524775dca82f1c502066b58e2d5712d7f87f5ba17c + version: 4.12.1 + resolution: "@eslint-community/regexpp@npm:4.12.1" + checksum: 10/c08f1dd7dd18fbb60bdd0d85820656d1374dd898af9be7f82cb00451313402a22d5e30569c150315b4385907cdbca78c22389b2a72ab78883b3173be317620cc languageName: node linkType: hard @@ -257,21 +407,21 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:8.57.0": - version: 8.57.0 - resolution: "@eslint/js@npm:8.57.0" - checksum: 10/3c501ce8a997cf6cbbaf4ed358af5492875e3550c19b9621413b82caa9ae5382c584b0efa79835639e6e0ddaa568caf3499318e5bdab68643ef4199dce5eb0a0 +"@eslint/js@npm:8.57.1": + version: 8.57.1 + resolution: "@eslint/js@npm:8.57.1" + checksum: 10/7562b21be10c2adbfa4aa5bb2eccec2cb9ac649a3569560742202c8d1cb6c931ce634937a2f0f551e078403a1c1285d6c2c0aa345dafc986149665cd69fe8b59 languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.11.14": - version: 0.11.14 - resolution: "@humanwhocodes/config-array@npm:0.11.14" +"@humanwhocodes/config-array@npm:^0.13.0": + version: 0.13.0 + resolution: "@humanwhocodes/config-array@npm:0.13.0" dependencies: - "@humanwhocodes/object-schema": "npm:^2.0.2" + "@humanwhocodes/object-schema": "npm:^2.0.3" debug: "npm:^4.3.1" minimatch: "npm:^3.0.5" - checksum: 10/3ffb24ecdfab64014a230e127118d50a1a04d11080cbb748bc21629393d100850496456bbcb4e8c438957fe0934430d731042f1264d6a167b62d32fc2863580a + checksum: 10/524df31e61a85392a2433bf5d03164e03da26c03d009f27852e7dcfdafbc4a23f17f021dacf88e0a7a9fe04ca032017945d19b57a16e2676d9114c22a53a9d11 languageName: node linkType: hard @@ -282,7 +432,7 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/object-schema@npm:^2.0.2": +"@humanwhocodes/object-schema@npm:^2.0.3": version: 2.0.3 resolution: "@humanwhocodes/object-schema@npm:2.0.3" checksum: 10/05bb99ed06c16408a45a833f03a732f59bf6184795d4efadd33238ff8699190a8c871ad1121241bb6501589a9598dc83bf25b99dcbcf41e155cdf36e35e937a3 @@ -303,15 +453,6 @@ __metadata: languageName: node linkType: hard -"@jest/schemas@npm:^29.6.3": - version: 29.6.3 - resolution: "@jest/schemas@npm:29.6.3" - dependencies: - "@sinclair/typebox": "npm:^0.27.8" - checksum: 10/910040425f0fc93cd13e68c750b7885590b8839066dfa0cd78e7def07bbb708ad869381f725945d66f2284de5663bbecf63e8fdd856e2ae6e261ba30b1687e93 - languageName: node - linkType: hard - "@jridgewell/gen-mapping@npm:^0.3.2": version: 0.3.5 resolution: "@jridgewell/gen-mapping@npm:0.3.5" @@ -411,8 +552,8 @@ __metadata: linkType: hard "@reduxjs/toolkit@npm:^2.0.1": - version: 2.2.7 - resolution: "@reduxjs/toolkit@npm:2.2.7" + version: 2.3.0 + resolution: "@reduxjs/toolkit@npm:2.3.0" dependencies: immer: "npm:^10.0.3" redux: "npm:^5.0.1" @@ -426,129 +567,136 @@ __metadata: optional: true react-redux: optional: true - checksum: 10/6bd1b5b44b12dbd53486c7dd05afc6d4bb7dc341ee3a44b5ed576b814db65babd5f81c5e3878ed5b2791dd4be01d4991e3a88e01ac5af11c260f4b9e4d5c30d9 + checksum: 10/3aa0bf29ce4dfe4ae75416cb5338a91ccc89f06c5a2fcdae5dc137dca02b3990c46306062696e158869ac399b50cae6476e5536902df9bd1ad1a998195221af6 languageName: node linkType: hard -"@rollup/rollup-android-arm-eabi@npm:4.21.3": - version: 4.21.3 - resolution: "@rollup/rollup-android-arm-eabi@npm:4.21.3" +"@rollup/rollup-android-arm-eabi@npm:4.26.0": + version: 4.26.0 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.26.0" conditions: os=android & cpu=arm languageName: node linkType: hard -"@rollup/rollup-android-arm64@npm:4.21.3": - version: 4.21.3 - resolution: "@rollup/rollup-android-arm64@npm:4.21.3" +"@rollup/rollup-android-arm64@npm:4.26.0": + version: 4.26.0 + resolution: "@rollup/rollup-android-arm64@npm:4.26.0" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-darwin-arm64@npm:4.21.3": - version: 4.21.3 - resolution: "@rollup/rollup-darwin-arm64@npm:4.21.3" +"@rollup/rollup-darwin-arm64@npm:4.26.0": + version: 4.26.0 + resolution: "@rollup/rollup-darwin-arm64@npm:4.26.0" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-darwin-x64@npm:4.21.3": - version: 4.21.3 - resolution: "@rollup/rollup-darwin-x64@npm:4.21.3" +"@rollup/rollup-darwin-x64@npm:4.26.0": + version: 4.26.0 + resolution: "@rollup/rollup-darwin-x64@npm:4.26.0" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@rollup/rollup-linux-arm-gnueabihf@npm:4.21.3": - version: 4.21.3 - resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.21.3" +"@rollup/rollup-freebsd-arm64@npm:4.26.0": + version: 4.26.0 + resolution: "@rollup/rollup-freebsd-arm64@npm:4.26.0" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-freebsd-x64@npm:4.26.0": + version: 4.26.0 + resolution: "@rollup/rollup-freebsd-x64@npm:4.26.0" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm-gnueabihf@npm:4.26.0": + version: 4.26.0 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.26.0" conditions: os=linux & cpu=arm & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-arm-musleabihf@npm:4.21.3": - version: 4.21.3 - resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.21.3" +"@rollup/rollup-linux-arm-musleabihf@npm:4.26.0": + version: 4.26.0 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.26.0" conditions: os=linux & cpu=arm & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-arm64-gnu@npm:4.21.3": - version: 4.21.3 - resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.21.3" +"@rollup/rollup-linux-arm64-gnu@npm:4.26.0": + version: 4.26.0 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.26.0" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-arm64-musl@npm:4.21.3": - version: 4.21.3 - resolution: "@rollup/rollup-linux-arm64-musl@npm:4.21.3" +"@rollup/rollup-linux-arm64-musl@npm:4.26.0": + version: 4.26.0 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.26.0" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-powerpc64le-gnu@npm:4.21.3": - version: 4.21.3 - resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.21.3" +"@rollup/rollup-linux-powerpc64le-gnu@npm:4.26.0": + version: 4.26.0 + resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.26.0" conditions: os=linux & cpu=ppc64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-riscv64-gnu@npm:4.21.3": - version: 4.21.3 - resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.21.3" +"@rollup/rollup-linux-riscv64-gnu@npm:4.26.0": + version: 4.26.0 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.26.0" conditions: os=linux & cpu=riscv64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-s390x-gnu@npm:4.21.3": - version: 4.21.3 - resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.21.3" +"@rollup/rollup-linux-s390x-gnu@npm:4.26.0": + version: 4.26.0 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.26.0" conditions: os=linux & cpu=s390x & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-x64-gnu@npm:4.21.3": - version: 4.21.3 - resolution: "@rollup/rollup-linux-x64-gnu@npm:4.21.3" +"@rollup/rollup-linux-x64-gnu@npm:4.26.0": + version: 4.26.0 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.26.0" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-x64-musl@npm:4.21.3": - version: 4.21.3 - resolution: "@rollup/rollup-linux-x64-musl@npm:4.21.3" +"@rollup/rollup-linux-x64-musl@npm:4.26.0": + version: 4.26.0 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.26.0" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-win32-arm64-msvc@npm:4.21.3": - version: 4.21.3 - resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.21.3" +"@rollup/rollup-win32-arm64-msvc@npm:4.26.0": + version: 4.26.0 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.26.0" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-win32-ia32-msvc@npm:4.21.3": - version: 4.21.3 - resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.21.3" +"@rollup/rollup-win32-ia32-msvc@npm:4.26.0": + version: 4.26.0 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.26.0" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@rollup/rollup-win32-x64-msvc@npm:4.21.3": - version: 4.21.3 - resolution: "@rollup/rollup-win32-x64-msvc@npm:4.21.3" +"@rollup/rollup-win32-x64-msvc@npm:4.26.0": + version: 4.26.0 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.26.0" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@sinclair/typebox@npm:^0.27.8": - version: 0.27.8 - resolution: "@sinclair/typebox@npm:0.27.8" - checksum: 10/297f95ff77c82c54de8c9907f186076e715ff2621c5222ba50b8d40a170661c0c5242c763cba2a4791f0f91cb1d8ffa53ea1d7294570cf8cd4694c0e383e484d - languageName: node - linkType: hard - "@testing-library/dom@npm:^9.0.0": version: 9.3.4 resolution: "@testing-library/dom@npm:9.3.4" @@ -586,10 +734,10 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:1.0.5, @types/estree@npm:^1.0.0": - version: 1.0.5 - resolution: "@types/estree@npm:1.0.5" - checksum: 10/7de6d928dd4010b0e20c6919e1a6c27b61f8d4567befa89252055fad503d587ecb9a1e3eab1b1901f923964d7019796db810b7fd6430acb26c32866d126fd408 +"@types/estree@npm:1.0.6, @types/estree@npm:^1.0.0": + version: 1.0.6 + resolution: "@types/estree@npm:1.0.6" + checksum: 10/9d35d475095199c23e05b431bcdd1f6fec7380612aed068b14b2a08aa70494de8a9026765a5a91b1073f636fb0368f6d8973f518a31391d519e20c59388ed88d languageName: node linkType: hard @@ -611,9 +759,9 @@ __metadata: linkType: hard "@types/lodash@npm:^4.14.175": - version: 4.17.7 - resolution: "@types/lodash@npm:4.17.7" - checksum: 10/b8177f19cf962414a66989837481b13f546afc2e98e8d465bec59e6ac03a59c584eb7053ce511cde3a09c5f3096d22a5ae22cfb56b23f3b0da75b0743b6b1a44 + version: 4.17.13 + resolution: "@types/lodash@npm:4.17.13" + checksum: 10/ddb34e20810c71be2d9445bcc4b64ec25b83976738454de709854b79c7f655b03704b76235445699956d65012987720e0e429a35489de65495cdb5420202d905 languageName: node linkType: hard @@ -624,38 +772,38 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*": - version: 22.5.4 - resolution: "@types/node@npm:22.5.4" +"@types/node@npm:*, @types/node@npm:^22.9.0": + version: 22.9.0 + resolution: "@types/node@npm:22.9.0" dependencies: - undici-types: "npm:~6.19.2" - checksum: 10/d46e0abf437b36bdf89011287aa43873d68ea6f2521a11b5c9a033056fd0d07af36daf51439010e8d41c62c55d0b00e9b5e09ed00bb2617723f73f28a873903a + undici-types: "npm:~6.19.8" + checksum: 10/a7df3426891868b0f5fb03e46aeddd8446178233521c624a44531c92a040cf08a82d8235f7e1e02af731fd16984665d4d71f3418caf9c2788313b10f040d615d languageName: node linkType: hard "@types/prop-types@npm:*": - version: 15.7.12 - resolution: "@types/prop-types@npm:15.7.12" - checksum: 10/ac16cc3d0a84431ffa5cfdf89579ad1e2269549f32ce0c769321fdd078f84db4fbe1b461ed5a1a496caf09e637c0e367d600c541435716a55b1d9713f5035dfe + version: 15.7.13 + resolution: "@types/prop-types@npm:15.7.13" + checksum: 10/8935cad87c683c665d09a055919d617fe951cb3b2d5c00544e3a913f861a2bd8d2145b51c9aa6d2457d19f3107ab40784c40205e757232f6a80cc8b1c815513c languageName: node linkType: hard "@types/react-dom@npm:^18.0.0, @types/react-dom@npm:^18.2.17": - version: 18.3.0 - resolution: "@types/react-dom@npm:18.3.0" + version: 18.3.1 + resolution: "@types/react-dom@npm:18.3.1" dependencies: "@types/react": "npm:*" - checksum: 10/6ff53f5a7b7fba952a68e114d3b542ebdc1e87a794234785ebab0bcd9bde7fb4885f21ebaf93d26dc0a1b5b93287f42cad68b78ae04dddf6b20da7aceff0beaf + checksum: 10/33f9ba79b26641ddf00a8699c30066b7e3573ab254e97475bf08f82fab83a6d3ce8d4ebad86afeb49bb8df3374390a9ba93125cece33badc4b3e8f7eac3c84d8 languageName: node linkType: hard "@types/react@npm:*, @types/react@npm:^18.2.38": - version: 18.3.5 - resolution: "@types/react@npm:18.3.5" + version: 18.3.12 + resolution: "@types/react@npm:18.3.12" dependencies: "@types/prop-types": "npm:*" csstype: "npm:^3.0.2" - checksum: 10/ba0477c5ad4a762157c6262a199af6ccf9e24576877a26a7f516d5a9ba35374a6ac7f8686a10e5e8030513214f02bcb66e8363e43905afb7cd313deaf673de05 + checksum: 10/c9bbdfeacd5347d2240e0d2cb5336bc57dbc1b9ff557b6c4024b49df83419e4955553518169d3736039f1b62608e15b35762a6c03d49bd86e33add4b43b19033 languageName: node linkType: hard @@ -846,57 +994,84 @@ __metadata: languageName: node linkType: hard -"@vitest/expect@npm:1.6.0": - version: 1.6.0 - resolution: "@vitest/expect@npm:1.6.0" +"@vitest/expect@npm:2.1.5": + version: 2.1.5 + resolution: "@vitest/expect@npm:2.1.5" dependencies: - "@vitest/spy": "npm:1.6.0" - "@vitest/utils": "npm:1.6.0" - chai: "npm:^4.3.10" - checksum: 10/e82304a12e22b98c1ccea81e8f33c838561deb878588eac463164cc4f8fc0c401ace3a9e6758d9e3a6bcc01313e845e8478aaefb7548eaded04b8de12c1928f6 + "@vitest/spy": "npm:2.1.5" + "@vitest/utils": "npm:2.1.5" + chai: "npm:^5.1.2" + tinyrainbow: "npm:^1.2.0" + checksum: 10/bc10f719c32f29e951754287d774a773535363d26a0425e85d0752fbf3cda3e168447522ef755ee5ac211f1916474feaac0d43f9e9e67c4260e202e532268429 languageName: node linkType: hard -"@vitest/runner@npm:1.6.0": - version: 1.6.0 - resolution: "@vitest/runner@npm:1.6.0" +"@vitest/mocker@npm:2.1.5": + version: 2.1.5 + resolution: "@vitest/mocker@npm:2.1.5" dependencies: - "@vitest/utils": "npm:1.6.0" - p-limit: "npm:^5.0.0" - pathe: "npm:^1.1.1" - checksum: 10/d83a608be36dace77f91a9d15ab7753f9c5923281188a8d9cb5ccec770df9cc9ba80e5e1e3465328c7605977be0f0708610855abf5f4af037a4ede5f51a83e47 + "@vitest/spy": "npm:2.1.5" + estree-walker: "npm:^3.0.3" + magic-string: "npm:^0.30.12" + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + checksum: 10/2557f2f77f4c7ac0cce79fcd62a99aa8d50979dca14fad1d0578e6f3b3d1855cdab1c7bbfa72a0468bf5f6f172b34b01116cc12758f4181d3819cd1e36a6751e languageName: node linkType: hard -"@vitest/snapshot@npm:1.6.0": - version: 1.6.0 - resolution: "@vitest/snapshot@npm:1.6.0" +"@vitest/pretty-format@npm:2.1.5, @vitest/pretty-format@npm:^2.1.5": + version: 2.1.5 + resolution: "@vitest/pretty-format@npm:2.1.5" dependencies: - magic-string: "npm:^0.30.5" - pathe: "npm:^1.1.1" - pretty-format: "npm:^29.7.0" - checksum: 10/0bfc26a48b45814604ff0f7276d73a047b79f3618e0b620ff54ea2de548e9603a9770963ba6ebb19f7ea1ed51001cbca58d74aa0271651d4f8e88c6233885eba + tinyrainbow: "npm:^1.2.0" + checksum: 10/98bf4e20c0efb893ffb2fe7713f84ccafd362d5022222ce097aab2368c2b0eccf3578d7ef4c26ea2f3d52e3c95f5fc7185ba36d7475d95537aab31ec4ac55d3a languageName: node linkType: hard -"@vitest/spy@npm:1.6.0": - version: 1.6.0 - resolution: "@vitest/spy@npm:1.6.0" +"@vitest/runner@npm:2.1.5": + version: 2.1.5 + resolution: "@vitest/runner@npm:2.1.5" dependencies: - tinyspy: "npm:^2.2.0" - checksum: 10/1c9698272a58aa47708bb8a1672d655fcec3285b02067cc3f70bfe76f4eda7a756eb379f8c945ccbe61677f5189aeb5ba93c2737a9d7db2de8c4e7bbdffcd372 + "@vitest/utils": "npm:2.1.5" + pathe: "npm:^1.1.2" + checksum: 10/7b47b089f52db06dee526030435ba3897e8dd7006c0c2d5498070fe10300ae76e46cdaa46562191c7be34544e6d447b0c861996de16659c97e5f7b92c82e5b8a languageName: node linkType: hard -"@vitest/utils@npm:1.6.0": - version: 1.6.0 - resolution: "@vitest/utils@npm:1.6.0" +"@vitest/snapshot@npm:2.1.5": + version: 2.1.5 + resolution: "@vitest/snapshot@npm:2.1.5" dependencies: - diff-sequences: "npm:^29.6.3" - estree-walker: "npm:^3.0.3" - loupe: "npm:^2.3.7" - pretty-format: "npm:^29.7.0" - checksum: 10/5c5d7295ac13fcea1da039232bcc7c3fc6f070070fe12ba2ad152456af6e216e48a3ae169016cfcd5055706a00dc567b8f62e4a9b1914f069f52b8f0a3c25e60 + "@vitest/pretty-format": "npm:2.1.5" + magic-string: "npm:^0.30.12" + pathe: "npm:^1.1.2" + checksum: 10/a650483fd76db5639ecbb168d599fcb45b020cb89a5ed8e3a74f3419852362a1b9ed443496e320cf3b8054e7b44f6537d67e280d2dfac99a53a2823321fdbf81 + languageName: node + linkType: hard + +"@vitest/spy@npm:2.1.5": + version: 2.1.5 + resolution: "@vitest/spy@npm:2.1.5" + dependencies: + tinyspy: "npm:^3.0.2" + checksum: 10/8985357bd571feec03c7b3f9941322ba88adbd30f1490485106e5fb6cf12655ae218776e2616b51439bf783db5bacbe4ecc26e674f053a0a9d6cd2f61213eac6 + languageName: node + linkType: hard + +"@vitest/utils@npm:2.1.5": + version: 2.1.5 + resolution: "@vitest/utils@npm:2.1.5" + dependencies: + "@vitest/pretty-format": "npm:2.1.5" + loupe: "npm:^3.1.2" + tinyrainbow: "npm:^1.2.0" + checksum: 10/c40c6784d26d0ae8f0125e01a4fe204bc6f6dc5179efaae194042040c4f52b974f3400dde3604f9ed963dba385464690c0c8177623236511e296f5e802cd8533 languageName: node linkType: hard @@ -916,21 +1091,12 @@ __metadata: languageName: node linkType: hard -"acorn-walk@npm:^8.3.2": - version: 8.3.4 - resolution: "acorn-walk@npm:8.3.4" - dependencies: - acorn: "npm:^8.11.0" - checksum: 10/871386764e1451c637bb8ab9f76f4995d408057e9909be6fb5ad68537ae3375d85e6a6f170b98989f44ab3ff6c74ad120bc2779a3d577606e7a0cd2b4efcaf77 - languageName: node - linkType: hard - -"acorn@npm:^8.11.0, acorn@npm:^8.11.3, acorn@npm:^8.9.0": - version: 8.12.1 - resolution: "acorn@npm:8.12.1" +"acorn@npm:^8.9.0": + version: 8.14.0 + resolution: "acorn@npm:8.14.0" bin: acorn: bin/acorn - checksum: 10/d08c2d122bba32d0861e0aa840b2ee25946c286d5dc5990abca991baf8cdbfbe199b05aacb221b979411a2fea36f83e26b5ac4f6b4e0ce49038c62316c1848f0 + checksum: 10/6df29c35556782ca9e632db461a7f97947772c6c1d5438a81f0c873a3da3a792487e83e404d1c6c25f70513e91aa18745f6eafb1fcc3a43ecd1920b21dd173d2 languageName: node linkType: hard @@ -979,15 +1145,6 @@ __metadata: languageName: node linkType: hard -"ansi-styles@npm:^3.2.1": - version: 3.2.1 - resolution: "ansi-styles@npm:3.2.1" - dependencies: - color-convert: "npm:^1.9.0" - checksum: 10/d85ade01c10e5dd77b6c89f34ed7531da5830d2cb5882c645f330079975b716438cd7ebb81d0d6e6b4f9c577f19ae41ab55f07f19786b02f9dfd9e0377395665 - languageName: node - linkType: hard - "ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0": version: 4.3.0 resolution: "ansi-styles@npm:4.3.0" @@ -1018,16 +1175,6 @@ __metadata: languageName: node linkType: hard -"anymatch@npm:~3.1.2": - version: 3.1.3 - resolution: "anymatch@npm:3.1.3" - dependencies: - normalize-path: "npm:^3.0.0" - picomatch: "npm:^2.0.4" - checksum: 10/3e044fd6d1d26545f235a9fe4d7a534e2029d8e59fa7fd9f2a6eb21230f6b5380ea1eaf55136e60cbf8e613544b3b766e7a6fa2102e2a3a117505466e3025dc2 - languageName: node - linkType: hard - "argparse@npm:^2.0.1": version: 2.0.1 resolution: "argparse@npm:2.0.1" @@ -1142,10 +1289,10 @@ __metadata: languageName: node linkType: hard -"assertion-error@npm:^1.1.0": - version: 1.1.0 - resolution: "assertion-error@npm:1.1.0" - checksum: 10/fd9429d3a3d4fd61782eb3962ae76b6d08aa7383123fca0596020013b3ebd6647891a85b05ce821c47d1471ed1271f00b0545cf6a4326cf2fc91efcc3b0fbecf +"assertion-error@npm:^2.0.1": + version: 2.0.1 + resolution: "assertion-error@npm:2.0.1" + checksum: 10/a0789dd882211b87116e81e2648ccb7f60340b34f19877dd020b39ebb4714e475eb943e14ba3e22201c221ef6645b7bfe10297e76b6ac95b48a9898c1211ce66 languageName: node linkType: hard @@ -1181,13 +1328,6 @@ __metadata: languageName: node linkType: hard -"binary-extensions@npm:^2.0.0": - version: 2.3.0 - resolution: "binary-extensions@npm:2.3.0" - checksum: 10/bcad01494e8a9283abf18c1b967af65ee79b0c6a9e6fcfafebfe91dbe6e0fc7272bafb73389e198b310516ae04f7ad17d79aacf6cb4c0d5d5202a7e2e52c7d98 - languageName: node - linkType: hard - "brace-expansion@npm:^1.1.7": version: 1.1.11 resolution: "brace-expansion@npm:1.1.11" @@ -1207,7 +1347,7 @@ __metadata: languageName: node linkType: hard -"braces@npm:^3.0.3, braces@npm:~3.0.2": +"braces@npm:^3.0.3": version: 3.0.3 resolution: "braces@npm:3.0.3" dependencies: @@ -1274,29 +1414,16 @@ __metadata: languageName: node linkType: hard -"chai@npm:^4.3.10": - version: 4.5.0 - resolution: "chai@npm:4.5.0" - dependencies: - assertion-error: "npm:^1.1.0" - check-error: "npm:^1.0.3" - deep-eql: "npm:^4.1.3" - get-func-name: "npm:^2.0.2" - loupe: "npm:^2.3.6" - pathval: "npm:^1.1.1" - type-detect: "npm:^4.1.0" - checksum: 10/cde341aee15b0a51559c7cfc20788dcfb4d586a498cfb93b937bb568fd45c777b73b1461274be6092b6bf868adb4e3a63f3fec13c89f7d8fb194f84c6fa42d5f - languageName: node - linkType: hard - -"chalk@npm:^2.4.2": - version: 2.4.2 - resolution: "chalk@npm:2.4.2" +"chai@npm:^5.1.2": + version: 5.1.2 + resolution: "chai@npm:5.1.2" dependencies: - ansi-styles: "npm:^3.2.1" - escape-string-regexp: "npm:^1.0.5" - supports-color: "npm:^5.3.0" - checksum: 10/3d1d103433166f6bfe82ac75724951b33769675252d8417317363ef9d54699b7c3b2d46671b772b893a8e50c3ece70c4b933c73c01e81bc60ea4df9b55afa303 + assertion-error: "npm:^2.0.1" + check-error: "npm:^2.1.1" + deep-eql: "npm:^5.0.1" + loupe: "npm:^3.1.0" + pathval: "npm:^2.0.0" + checksum: 10/e8c2bbc83cb5a2f87130d93056d4cfbbe04106e12aa798b504816dbe3fa538a9f68541b472e56cbf0f54558b501d7e31867d74b8218abcd5a8cc8ba536fba46c languageName: node linkType: hard @@ -1310,31 +1437,19 @@ __metadata: languageName: node linkType: hard -"check-error@npm:^1.0.3": - version: 1.0.3 - resolution: "check-error@npm:1.0.3" - dependencies: - get-func-name: "npm:^2.0.2" - checksum: 10/e2131025cf059b21080f4813e55b3c480419256914601750b0fee3bd9b2b8315b531e551ef12560419b8b6d92a3636511322752b1ce905703239e7cc451b6399 +"check-error@npm:^2.1.1": + version: 2.1.1 + resolution: "check-error@npm:2.1.1" + checksum: 10/d785ed17b1d4a4796b6e75c765a9a290098cf52ff9728ce0756e8ffd4293d2e419dd30c67200aee34202463b474306913f2fcfaf1890641026d9fc6966fea27a languageName: node linkType: hard -"chokidar@npm:^3.6.0": - version: 3.6.0 - resolution: "chokidar@npm:3.6.0" +"chokidar@npm:^4.0.1": + version: 4.0.1 + resolution: "chokidar@npm:4.0.1" dependencies: - anymatch: "npm:~3.1.2" - braces: "npm:~3.0.2" - fsevents: "npm:~2.3.2" - glob-parent: "npm:~5.1.2" - is-binary-path: "npm:~2.1.0" - is-glob: "npm:~4.0.1" - normalize-path: "npm:~3.0.0" - readdirp: "npm:~3.6.0" - dependenciesMeta: - fsevents: - optional: true - checksum: 10/c327fb07704443f8d15f7b4a7ce93b2f0bc0e6cea07ec28a7570aa22cd51fcf0379df589403976ea956c369f25aa82d84561947e227cd925902e1751371658df + readdirp: "npm:^4.0.1" + checksum: 10/62749d2173a60cc5632d6c6e0b7024f33aadce47b06d02e55ad03c7b8daaaf2fc85d4296c047473d04387fd992dab9384cc5263c70a3dc3018b7ebecfb5b5217 languageName: node linkType: hard @@ -1363,15 +1478,6 @@ __metadata: languageName: node linkType: hard -"color-convert@npm:^1.9.0": - version: 1.9.3 - resolution: "color-convert@npm:1.9.3" - dependencies: - color-name: "npm:1.1.3" - checksum: 10/ffa319025045f2973919d155f25e7c00d08836b6b33ea2d205418c59bd63a665d713c52d9737a9e0fe467fb194b40fbef1d849bae80d674568ee220a31ef3d10 - languageName: node - linkType: hard - "color-convert@npm:^2.0.1": version: 2.0.1 resolution: "color-convert@npm:2.0.1" @@ -1381,13 +1487,6 @@ __metadata: languageName: node linkType: hard -"color-name@npm:1.1.3": - version: 1.1.3 - resolution: "color-name@npm:1.1.3" - checksum: 10/09c5d3e33d2105850153b14466501f2bfb30324a2f76568a408763a3b7433b0e50e5b4ab1947868e65cb101bb7cb75029553f2c333b6d4b8138a73fcc133d69d - languageName: node - linkType: hard - "color-name@npm:~1.1.4": version: 1.1.4 resolution: "color-name@npm:1.1.4" @@ -1418,13 +1517,6 @@ __metadata: languageName: node linkType: hard -"confbox@npm:^0.1.7": - version: 0.1.7 - resolution: "confbox@npm:0.1.7" - checksum: 10/3086687b9a2a70d44d4b40a2d376536fe7e1baec4a2a34261b21b8a836026b419cbf89ded6054216631823e7d63c415dad4b4d53591d6edbb202bb9820dfa6fa - languageName: node - linkType: hard - "consola@npm:^3.2.3": version: 3.2.3 resolution: "consola@npm:3.2.3" @@ -1432,14 +1524,14 @@ __metadata: languageName: node linkType: hard -"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": - version: 7.0.3 - resolution: "cross-spawn@npm:7.0.3" +"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2": + version: 7.0.5 + resolution: "cross-spawn@npm:7.0.5" dependencies: path-key: "npm:^3.1.0" shebang-command: "npm:^2.0.0" which: "npm:^2.0.1" - checksum: 10/e1a13869d2f57d974de0d9ef7acbf69dc6937db20b918525a01dacb5032129bd552d290d886d981e99f1b624cb03657084cc87bd40f115c07ecf376821c729ce + checksum: 10/c95062469d4bdbc1f099454d01c0e77177a3733012d41bf907a71eb8d22d2add43b5adf6a0a14ef4e7feaf804082714d6c262ef4557a1c480b86786c120d18e2 languageName: node linkType: hard @@ -1512,7 +1604,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.5": +"debug@npm:4, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.7": version: 4.3.7 resolution: "debug@npm:4.3.7" dependencies: @@ -1531,12 +1623,10 @@ __metadata: languageName: node linkType: hard -"deep-eql@npm:^4.1.3": - version: 4.1.4 - resolution: "deep-eql@npm:4.1.4" - dependencies: - type-detect: "npm:^4.0.0" - checksum: 10/f04f4d581f044a824a6322fe4f68fbee4d6780e93fc710cd9852cbc82bfc7010df00f0e05894b848abbe14dc3a25acac44f424e181ae64d12f2ab9d0a875a5ef +"deep-eql@npm:^5.0.1": + version: 5.0.2 + resolution: "deep-eql@npm:5.0.2" + checksum: 10/a529b81e2ef8821621d20a36959a0328873a3e49d393ad11f8efe8559f31239494c2eb889b80342808674c475802ba95b9d6c4c27641b9a029405104c1b59fcf languageName: node linkType: hard @@ -1602,13 +1692,6 @@ __metadata: languageName: node linkType: hard -"diff-sequences@npm:^29.6.3": - version: 29.6.3 - resolution: "diff-sequences@npm:29.6.3" - checksum: 10/179daf9d2f9af5c57ad66d97cb902a538bcf8ed64963fa7aa0c329b3de3665ce2eb6ffdc2f69f29d445fa4af2517e5e55e5b6e00c00a9ae4f43645f97f7078cb - languageName: node - linkType: hard - "dir-glob@npm:^3.0.1": version: 3.0.1 resolution: "dir-glob@npm:3.0.1" @@ -1673,7 +1756,7 @@ __metadata: languageName: node linkType: hard -"entities@npm:^4.4.0": +"entities@npm:^4.5.0": version: 4.5.0 resolution: "entities@npm:4.5.0" checksum: 10/ede2a35c9bce1aeccd055a1b445d41c75a14a2bb1cd22e242f20cf04d236cdcd7f9c859eb83f76885327bfae0c25bf03303665ee1ce3d47c5927b98b0e3e3d48 @@ -1695,8 +1778,8 @@ __metadata: linkType: hard "es-abstract@npm:^1.17.5, es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.1, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3": - version: 1.23.3 - resolution: "es-abstract@npm:1.23.3" + version: 1.23.4 + resolution: "es-abstract@npm:1.23.4" dependencies: array-buffer-byte-length: "npm:^1.0.1" arraybuffer.prototype.slice: "npm:^1.0.3" @@ -1713,7 +1796,7 @@ __metadata: function.prototype.name: "npm:^1.1.6" get-intrinsic: "npm:^1.2.4" get-symbol-description: "npm:^1.0.2" - globalthis: "npm:^1.0.3" + globalthis: "npm:^1.0.4" gopd: "npm:^1.0.1" has-property-descriptors: "npm:^1.0.2" has-proto: "npm:^1.0.3" @@ -1729,10 +1812,10 @@ __metadata: is-string: "npm:^1.0.7" is-typed-array: "npm:^1.1.13" is-weakref: "npm:^1.0.2" - object-inspect: "npm:^1.13.1" + object-inspect: "npm:^1.13.3" object-keys: "npm:^1.1.1" object.assign: "npm:^4.1.5" - regexp.prototype.flags: "npm:^1.5.2" + regexp.prototype.flags: "npm:^1.5.3" safe-array-concat: "npm:^1.1.2" safe-regex-test: "npm:^1.0.3" string.prototype.trim: "npm:^1.2.9" @@ -1744,7 +1827,7 @@ __metadata: typed-array-length: "npm:^1.0.6" unbox-primitive: "npm:^1.0.2" which-typed-array: "npm:^1.1.15" - checksum: 10/2da795a6a1ac5fc2c452799a409acc2e3692e06dc6440440b076908617188899caa562154d77263e3053bcd9389a07baa978ab10ac3b46acc399bd0c77be04cb + checksum: 10/ab8165900b758ee4d5a8d39c150f33a86edfe8dae3e92556707911247bc4db51aefc924d1c56cefb3858ea613a58fac59eeeb959d86115d0c5cde3a6abff5a50 languageName: node linkType: hard @@ -1781,9 +1864,9 @@ __metadata: languageName: node linkType: hard -"es-iterator-helpers@npm:^1.0.19": - version: 1.0.19 - resolution: "es-iterator-helpers@npm:1.0.19" +"es-iterator-helpers@npm:^1.1.0": + version: 1.2.0 + resolution: "es-iterator-helpers@npm:1.2.0" dependencies: call-bind: "npm:^1.0.7" define-properties: "npm:^1.2.1" @@ -1792,14 +1875,22 @@ __metadata: es-set-tostringtag: "npm:^2.0.3" function-bind: "npm:^1.1.2" get-intrinsic: "npm:^1.2.4" - globalthis: "npm:^1.0.3" + globalthis: "npm:^1.0.4" + gopd: "npm:^1.0.1" has-property-descriptors: "npm:^1.0.2" has-proto: "npm:^1.0.3" has-symbols: "npm:^1.0.3" internal-slot: "npm:^1.0.7" - iterator.prototype: "npm:^1.1.2" + iterator.prototype: "npm:^1.1.3" safe-array-concat: "npm:^1.1.2" - checksum: 10/980a8081cf6798fe17fcea193b0448d784d72d76aca7240b10813207c67e3dc0d8a23992263870c4fc291da5a946935b0c56dec4fa1a9de8fee0165e4fa1fc58 + checksum: 10/a4159e36c6bae03d4b636894fff2ff1acfcedc16c622939298b00adf4d2da6356ad92f682cc75c037a012a4b06adb903f67dfdfd05bac61847e9b763de2acbcb + languageName: node + linkType: hard + +"es-module-lexer@npm:^1.5.4": + version: 1.5.4 + resolution: "es-module-lexer@npm:1.5.4" + checksum: 10/f29c7c97a58eb17640dcbd71bd6ef754ad4f58f95c3073894573d29dae2cad43ecd2060d97ed5b866dfb7804d5590fb7de1d2c5339a5fceae8bd60b580387fc5 languageName: node linkType: hard @@ -1843,34 +1934,114 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:0.23.0": - version: 0.23.0 - resolution: "esbuild@npm:0.23.0" - dependencies: - "@esbuild/aix-ppc64": "npm:0.23.0" - "@esbuild/android-arm": "npm:0.23.0" - "@esbuild/android-arm64": "npm:0.23.0" - "@esbuild/android-x64": "npm:0.23.0" - "@esbuild/darwin-arm64": "npm:0.23.0" - "@esbuild/darwin-x64": "npm:0.23.0" - "@esbuild/freebsd-arm64": "npm:0.23.0" - "@esbuild/freebsd-x64": "npm:0.23.0" - "@esbuild/linux-arm": "npm:0.23.0" - "@esbuild/linux-arm64": "npm:0.23.0" - "@esbuild/linux-ia32": "npm:0.23.0" - "@esbuild/linux-loong64": "npm:0.23.0" - "@esbuild/linux-mips64el": "npm:0.23.0" - "@esbuild/linux-ppc64": "npm:0.23.0" - "@esbuild/linux-riscv64": "npm:0.23.0" - "@esbuild/linux-s390x": "npm:0.23.0" - "@esbuild/linux-x64": "npm:0.23.0" - "@esbuild/netbsd-x64": "npm:0.23.0" - "@esbuild/openbsd-arm64": "npm:0.23.0" - "@esbuild/openbsd-x64": "npm:0.23.0" - "@esbuild/sunos-x64": "npm:0.23.0" - "@esbuild/win32-arm64": "npm:0.23.0" - "@esbuild/win32-ia32": "npm:0.23.0" - "@esbuild/win32-x64": "npm:0.23.0" +"esbuild@npm:^0.21.3": + version: 0.21.5 + resolution: "esbuild@npm:0.21.5" + dependencies: + "@esbuild/aix-ppc64": "npm:0.21.5" + "@esbuild/android-arm": "npm:0.21.5" + "@esbuild/android-arm64": "npm:0.21.5" + "@esbuild/android-x64": "npm:0.21.5" + "@esbuild/darwin-arm64": "npm:0.21.5" + "@esbuild/darwin-x64": "npm:0.21.5" + "@esbuild/freebsd-arm64": "npm:0.21.5" + "@esbuild/freebsd-x64": "npm:0.21.5" + "@esbuild/linux-arm": "npm:0.21.5" + "@esbuild/linux-arm64": "npm:0.21.5" + "@esbuild/linux-ia32": "npm:0.21.5" + "@esbuild/linux-loong64": "npm:0.21.5" + "@esbuild/linux-mips64el": "npm:0.21.5" + "@esbuild/linux-ppc64": "npm:0.21.5" + "@esbuild/linux-riscv64": "npm:0.21.5" + "@esbuild/linux-s390x": "npm:0.21.5" + "@esbuild/linux-x64": "npm:0.21.5" + "@esbuild/netbsd-x64": "npm:0.21.5" + "@esbuild/openbsd-x64": "npm:0.21.5" + "@esbuild/sunos-x64": "npm:0.21.5" + "@esbuild/win32-arm64": "npm:0.21.5" + "@esbuild/win32-ia32": "npm:0.21.5" + "@esbuild/win32-x64": "npm:0.21.5" + dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: 10/d2ff2ca84d30cce8e871517374d6c2290835380dc7cd413b2d49189ed170d45e407be14de2cb4794cf76f75cf89955c4714726ebd3de7444b3046f5cab23ab6b + languageName: node + linkType: hard + +"esbuild@npm:^0.24.0": + version: 0.24.0 + resolution: "esbuild@npm:0.24.0" + dependencies: + "@esbuild/aix-ppc64": "npm:0.24.0" + "@esbuild/android-arm": "npm:0.24.0" + "@esbuild/android-arm64": "npm:0.24.0" + "@esbuild/android-x64": "npm:0.24.0" + "@esbuild/darwin-arm64": "npm:0.24.0" + "@esbuild/darwin-x64": "npm:0.24.0" + "@esbuild/freebsd-arm64": "npm:0.24.0" + "@esbuild/freebsd-x64": "npm:0.24.0" + "@esbuild/linux-arm": "npm:0.24.0" + "@esbuild/linux-arm64": "npm:0.24.0" + "@esbuild/linux-ia32": "npm:0.24.0" + "@esbuild/linux-loong64": "npm:0.24.0" + "@esbuild/linux-mips64el": "npm:0.24.0" + "@esbuild/linux-ppc64": "npm:0.24.0" + "@esbuild/linux-riscv64": "npm:0.24.0" + "@esbuild/linux-s390x": "npm:0.24.0" + "@esbuild/linux-x64": "npm:0.24.0" + "@esbuild/netbsd-x64": "npm:0.24.0" + "@esbuild/openbsd-arm64": "npm:0.24.0" + "@esbuild/openbsd-x64": "npm:0.24.0" + "@esbuild/sunos-x64": "npm:0.24.0" + "@esbuild/win32-arm64": "npm:0.24.0" + "@esbuild/win32-ia32": "npm:0.24.0" + "@esbuild/win32-x64": "npm:0.24.0" dependenciesMeta: "@esbuild/aix-ppc64": optional: true @@ -1922,7 +2093,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 10/d3d91bf9ca73ba33966fc54cabb321eca770a5e2ff5b34d67e4235c94560cfd881803e39fcaa31d842579d10600da5201c5f597f8438679f6db856f75ded7124 + checksum: 10/500f83a1216d6548053007b85c070d8293395db344605b17418c6cf1217e5e8d338fa77fc8af27c23faa121c5528e5b0004d46d3a0cdeb87d48f1b5fa0164bc5 languageName: node linkType: hard @@ -1933,13 +2104,6 @@ __metadata: languageName: node linkType: hard -"escape-string-regexp@npm:^1.0.5": - version: 1.0.5 - resolution: "escape-string-regexp@npm:1.0.5" - checksum: 10/6092fda75c63b110c706b6a9bfde8a612ad595b628f0bd2147eea1d3406723020810e591effc7db1da91d80a71a737a313567c5abb3813e8d9c71f4aa595b410 - languageName: node - linkType: hard - "escape-string-regexp@npm:^4.0.0": version: 4.0.0 resolution: "escape-string-regexp@npm:4.0.0" @@ -1948,15 +2112,15 @@ __metadata: linkType: hard "eslint-plugin-react@npm:^7.26.1": - version: 7.36.0 - resolution: "eslint-plugin-react@npm:7.36.0" + version: 7.37.2 + resolution: "eslint-plugin-react@npm:7.37.2" dependencies: array-includes: "npm:^3.1.8" array.prototype.findlast: "npm:^1.2.5" array.prototype.flatmap: "npm:^1.3.2" array.prototype.tosorted: "npm:^1.1.4" doctrine: "npm:^2.1.0" - es-iterator-helpers: "npm:^1.0.19" + es-iterator-helpers: "npm:^1.1.0" estraverse: "npm:^5.3.0" hasown: "npm:^2.0.2" jsx-ast-utils: "npm:^2.4.1 || ^3.0.0" @@ -1971,7 +2135,7 @@ __metadata: string.prototype.repeat: "npm:^1.0.0" peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 - checksum: 10/f28098e02f611fbdde36c9ef3b256a5c51c7ec0cc21ddcf9ac45f3b8f53728fc2dcb91dbd3de1ae234c6941d336e5045d4b32c09d50be29e4e2663b13f8bd2f1 + checksum: 10/df2f7ab198018d3378f305a8a5ceceebc9bd31f019fc7567a2ef9c77789dc8a6a2c3c3957f8b0805f26c11c02f9f86c972e02cd0eda12f4d0370526c11f8a9a3 languageName: node linkType: hard @@ -1994,7 +2158,7 @@ __metadata: languageName: node linkType: hard -"eslint-visitor-keys@npm:^3.3.0, eslint-visitor-keys@npm:^3.4.1, eslint-visitor-keys@npm:^3.4.3": +"eslint-visitor-keys@npm:^3.4.1, eslint-visitor-keys@npm:^3.4.3": version: 3.4.3 resolution: "eslint-visitor-keys@npm:3.4.3" checksum: 10/3f357c554a9ea794b094a09bd4187e5eacd1bc0d0653c3adeb87962c548e6a1ab8f982b86963ae1337f5d976004146536dcee5d0e2806665b193fbfbf1a9231b @@ -2002,14 +2166,14 @@ __metadata: linkType: hard "eslint@npm:^8.0.1": - version: 8.57.0 - resolution: "eslint@npm:8.57.0" + version: 8.57.1 + resolution: "eslint@npm:8.57.1" dependencies: "@eslint-community/eslint-utils": "npm:^4.2.0" "@eslint-community/regexpp": "npm:^4.6.1" "@eslint/eslintrc": "npm:^2.1.4" - "@eslint/js": "npm:8.57.0" - "@humanwhocodes/config-array": "npm:^0.11.14" + "@eslint/js": "npm:8.57.1" + "@humanwhocodes/config-array": "npm:^0.13.0" "@humanwhocodes/module-importer": "npm:^1.0.1" "@nodelib/fs.walk": "npm:^1.2.8" "@ungap/structured-clone": "npm:^1.2.0" @@ -2045,7 +2209,7 @@ __metadata: text-table: "npm:^0.2.0" bin: eslint: bin/eslint.js - checksum: 10/00496e218b23747a7a9817bf58b522276d0dc1f2e546dceb4eea49f9871574088f72f1f069a6b560ef537efa3a75261b8ef70e51ef19033da1cc4c86a755ef15 + checksum: 10/5504fa24879afdd9f9929b2fbfc2ee9b9441a3d464efd9790fbda5f05738858530182029f13323add68d19fec749d3ab4a70320ded091ca4432b1e9cc4ed104c languageName: node linkType: hard @@ -2101,40 +2265,6 @@ __metadata: languageName: node linkType: hard -"execa@npm:^5.1.1": - version: 5.1.1 - resolution: "execa@npm:5.1.1" - dependencies: - cross-spawn: "npm:^7.0.3" - get-stream: "npm:^6.0.0" - human-signals: "npm:^2.1.0" - is-stream: "npm:^2.0.0" - merge-stream: "npm:^2.0.0" - npm-run-path: "npm:^4.0.1" - onetime: "npm:^5.1.2" - signal-exit: "npm:^3.0.3" - strip-final-newline: "npm:^2.0.0" - checksum: 10/8ada91f2d70f7dff702c861c2c64f21dfdc1525628f3c0454fd6f02fce65f7b958616cbd2b99ca7fa4d474e461a3d363824e91b3eb881705231abbf387470597 - languageName: node - linkType: hard - -"execa@npm:^8.0.1": - version: 8.0.1 - resolution: "execa@npm:8.0.1" - dependencies: - cross-spawn: "npm:^7.0.3" - get-stream: "npm:^8.0.1" - human-signals: "npm:^5.0.0" - is-stream: "npm:^3.0.0" - merge-stream: "npm:^2.0.0" - npm-run-path: "npm:^5.1.0" - onetime: "npm:^6.0.0" - signal-exit: "npm:^4.1.0" - strip-final-newline: "npm:^3.0.0" - checksum: 10/d2ab5fe1e2bb92b9788864d0713f1fce9a07c4594e272c0c97bc18c90569897ab262e4ea58d27a694d288227a2e24f16f5e2575b44224ad9983b799dc7f1098d - languageName: node - linkType: hard - "exit@npm:^0.1.2": version: 0.1.2 resolution: "exit@npm:0.1.2" @@ -2142,6 +2272,13 @@ __metadata: languageName: node linkType: hard +"expect-type@npm:^1.1.0": + version: 1.1.0 + resolution: "expect-type@npm:1.1.0" + checksum: 10/05fca80ddc7d493a89361f783c6b000750fa04a8226bc24701f3b90adb0efc2fb467f2a0baaed4015a02d8b9034ef5bb87521df9dba980f50b1105bd596ef833 + languageName: node + linkType: hard + "exponential-backoff@npm:^3.1.1": version: 3.1.1 resolution: "exponential-backoff@npm:3.1.1" @@ -2192,6 +2329,18 @@ __metadata: languageName: node linkType: hard +"fdir@npm:^6.4.2": + version: 6.4.2 + resolution: "fdir@npm:6.4.2" + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + checksum: 10/5ff80d1d2034e75cc68be175401c9f64c4938a6b2c1e9a0c27f2d211ffbe491fd86d29e4576825d9da8aff9bd465f0283427c2dddc11653457906c46d3bbc448 + languageName: node + linkType: hard + "file-entry-cache@npm:^6.0.1": version: 6.0.1 resolution: "file-entry-cache@npm:6.0.1" @@ -2258,13 +2407,13 @@ __metadata: linkType: hard "form-data@npm:^4.0.0": - version: 4.0.0 - resolution: "form-data@npm:4.0.0" + version: 4.0.1 + resolution: "form-data@npm:4.0.1" dependencies: asynckit: "npm:^0.4.0" combined-stream: "npm:^1.0.8" mime-types: "npm:^2.1.12" - checksum: 10/7264aa760a8cf09482816d8300f1b6e2423de1b02bba612a136857413fdc96d7178298ced106817655facc6b89036c6e12ae31c9eb5bdc16aabf502ae8a5d805 + checksum: 10/6adb1cff557328bc6eb8a68da205f9ae44ab0e88d4d9237aaf91eed591ffc64f77411efb9016af7d87f23d0a038c45a788aa1c6634e51175c4efa36c2bc53774 languageName: node linkType: hard @@ -2345,13 +2494,6 @@ __metadata: languageName: node linkType: hard -"get-func-name@npm:^2.0.1, get-func-name@npm:^2.0.2": - version: 2.0.2 - resolution: "get-func-name@npm:2.0.2" - checksum: 10/3f62f4c23647de9d46e6f76d2b3eafe58933a9b3830c60669e4180d6c601ce1b4aa310ba8366143f55e52b139f992087a9f0647274e8745621fa2af7e0acf13b - languageName: node - linkType: hard - "get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4": version: 1.2.4 resolution: "get-intrinsic@npm:1.2.4" @@ -2365,20 +2507,6 @@ __metadata: languageName: node linkType: hard -"get-stream@npm:^6.0.0": - version: 6.0.1 - resolution: "get-stream@npm:6.0.1" - checksum: 10/781266d29725f35c59f1d214aedc92b0ae855800a980800e2923b3fbc4e56b3cb6e462c42e09a1cf1a00c64e056a78fa407cbe06c7c92b7e5cd49b4b85c2a497 - languageName: node - linkType: hard - -"get-stream@npm:^8.0.1": - version: 8.0.1 - resolution: "get-stream@npm:8.0.1" - checksum: 10/dde5511e2e65a48e9af80fea64aff11b4921b14b6e874c6f8294c50975095af08f41bfb0b680c887f28b566dd6ec2cb2f960f9d36a323359be324ce98b766e9e - languageName: node - linkType: hard - "get-symbol-description@npm:^1.0.2": version: 1.0.2 resolution: "get-symbol-description@npm:1.0.2" @@ -2390,7 +2518,7 @@ __metadata: languageName: node linkType: hard -"glob-parent@npm:^5.1.2, glob-parent@npm:~5.1.2": +"glob-parent@npm:^5.1.2": version: 5.1.2 resolution: "glob-parent@npm:5.1.2" dependencies: @@ -2447,7 +2575,7 @@ __metadata: languageName: node linkType: hard -"globalthis@npm:^1.0.3": +"globalthis@npm:^1.0.3, globalthis@npm:^1.0.4": version: 1.0.4 resolution: "globalthis@npm:1.0.4" dependencies: @@ -2501,13 +2629,6 @@ __metadata: languageName: node linkType: hard -"has-flag@npm:^3.0.0": - version: 3.0.0 - resolution: "has-flag@npm:3.0.0" - checksum: 10/4a15638b454bf086c8148979aae044dd6e39d63904cd452d970374fa6a87623423da485dfb814e7be882e05c096a7ccf1ebd48e7e7501d0208d8384ff4dea73b - languageName: node - linkType: hard - "has-flag@npm:^4.0.0": version: 4.0.0 resolution: "has-flag@npm:4.0.0" @@ -2592,20 +2713,6 @@ __metadata: languageName: node linkType: hard -"human-signals@npm:^2.1.0": - version: 2.1.0 - resolution: "human-signals@npm:2.1.0" - checksum: 10/df59be9e0af479036798a881d1f136c4a29e0b518d4abb863afbd11bf30efa3eeb1d0425fc65942dcc05ab3bf40205ea436b0ff389f2cd20b75b8643d539bf86 - languageName: node - linkType: hard - -"human-signals@npm:^5.0.0": - version: 5.0.0 - resolution: "human-signals@npm:5.0.0" - checksum: 10/30f8870d831cdcd2d6ec0486a7d35d49384996742052cee792854273fa9dd9e7d5db06bb7985d4953e337e10714e994e0302e90dc6848069171b05ec836d65b0 - languageName: node - linkType: hard - "iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2": version: 0.6.3 resolution: "iconv-lite@npm:0.6.3" @@ -2736,15 +2843,6 @@ __metadata: languageName: node linkType: hard -"is-binary-path@npm:~2.1.0": - version: 2.1.0 - resolution: "is-binary-path@npm:2.1.0" - dependencies: - binary-extensions: "npm:^2.0.0" - checksum: 10/078e51b4f956c2c5fd2b26bb2672c3ccf7e1faff38e0ebdba45612265f4e3d9fc3127a1fa8370bbf09eab61339203c3d3b7af5662cbf8be4030f8fac37745b0e - languageName: node - linkType: hard - "is-boolean-object@npm:^1.1.0": version: 1.1.2 resolution: "is-boolean-object@npm:1.1.2" @@ -2821,7 +2919,7 @@ __metadata: languageName: node linkType: hard -"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3, is-glob@npm:~4.0.1": +"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3": version: 4.0.3 resolution: "is-glob@npm:4.0.3" dependencies: @@ -2907,20 +3005,6 @@ __metadata: languageName: node linkType: hard -"is-stream@npm:^2.0.0": - version: 2.0.1 - resolution: "is-stream@npm:2.0.1" - checksum: 10/b8e05ccdf96ac330ea83c12450304d4a591f9958c11fd17bed240af8d5ffe08aedafa4c0f4cfccd4d28dc9d4d129daca1023633d5c11601a6cbc77521f6fae66 - languageName: node - linkType: hard - -"is-stream@npm:^3.0.0": - version: 3.0.0 - resolution: "is-stream@npm:3.0.0" - checksum: 10/172093fe99119ffd07611ab6d1bcccfe8bc4aa80d864b15f43e63e54b7abc71e779acd69afdb854c4e2a67fdc16ae710e370eda40088d1cfc956a50ed82d8f16 - languageName: node - linkType: hard - "is-string@npm:^1.0.5, is-string@npm:^1.0.7": version: 1.0.7 resolution: "is-string@npm:1.0.7" @@ -2995,16 +3079,16 @@ __metadata: languageName: node linkType: hard -"iterator.prototype@npm:^1.1.2": - version: 1.1.2 - resolution: "iterator.prototype@npm:1.1.2" +"iterator.prototype@npm:^1.1.3": + version: 1.1.3 + resolution: "iterator.prototype@npm:1.1.3" dependencies: define-properties: "npm:^1.2.1" get-intrinsic: "npm:^1.2.1" has-symbols: "npm:^1.0.3" reflect.getprototypeof: "npm:^1.0.4" set-function-name: "npm:^2.0.1" - checksum: 10/b5013967ad8f28c9ca1be8e159eb10f591b8e46deae87476fe39d668c04374fe9158c815e8b6d2f45885b0a3fd842a8ba13f497ec762b3a0eff49bec278670b1 + checksum: 10/1a2a508d3baac121b76c834404ff552d1bb96a173b1d74ff947b2c5763840c0b1e5be01be7e2183a19b08e99e38729812668ff1f23b35f6655a366017bc32519 languageName: node linkType: hard @@ -3035,13 +3119,6 @@ __metadata: languageName: node linkType: hard -"js-tokens@npm:^9.0.0": - version: 9.0.0 - resolution: "js-tokens@npm:9.0.0" - checksum: 10/65e7a55a1a18d61f1cf94bfd7704da870b74337fa08d4c58118e69a8b10225b5ad887ff3ae595d720301b0924811a9b0594c679621a85ecbac6e3aac8533c53b - languageName: node - linkType: hard - "js-yaml@npm:^4.1.0": version: 4.1.0 resolution: "js-yaml@npm:4.1.0" @@ -3186,16 +3263,6 @@ __metadata: languageName: node linkType: hard -"local-pkg@npm:^0.5.0": - version: 0.5.0 - resolution: "local-pkg@npm:0.5.0" - dependencies: - mlly: "npm:^1.4.2" - pkg-types: "npm:^1.0.3" - checksum: 10/20f4caba50dc6fb00ffcc1a78bc94b5acb33995e0aadf4d4edcdeab257e891aa08f50afddf02f3240b2c3d02432bc2078f2a916a280ed716b64753a3d250db70 - languageName: node - linkType: hard - "locate-path@npm:^6.0.0": version: 6.0.0 resolution: "locate-path@npm:6.0.0" @@ -3244,12 +3311,10 @@ __metadata: languageName: node linkType: hard -"loupe@npm:^2.3.6, loupe@npm:^2.3.7": - version: 2.3.7 - resolution: "loupe@npm:2.3.7" - dependencies: - get-func-name: "npm:^2.0.1" - checksum: 10/635c8f0914c2ce7ecfe4e239fbaf0ce1d2c00e4246fafcc4ed000bfdb1b8f89d05db1a220054175cca631ebf3894872a26fffba0124477fcb562f78762848fb1 +"loupe@npm:^3.1.0, loupe@npm:^3.1.2": + version: 3.1.2 + resolution: "loupe@npm:3.1.2" + checksum: 10/8f5734e53fb64cd914aa7d986e01b6d4c2e3c6c56dcbd5428d71c2703f0ab46b5ab9f9eeaaf2b485e8a1c43f865bdd16ec08ae1a661c8f55acdbd9f4d59c607a languageName: node linkType: hard @@ -3269,12 +3334,12 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:^0.30.5": - version: 0.30.11 - resolution: "magic-string@npm:0.30.11" +"magic-string@npm:^0.30.12": + version: 0.30.12 + resolution: "magic-string@npm:0.30.12" dependencies: "@jridgewell/sourcemap-codec": "npm:^1.5.0" - checksum: 10/b784d2240252f5b1e755d487354ada4c672cbca16f045144f7185a75b059210e5fcca7be7be03ef1bac2ca754c4428b21d36ae64a9057ba429916f06b8c54eb2 + checksum: 10/98016180a52b28efc1362152b45671067facccdaead6b70c1c14c566cba98491bc2e1336474b0996397730dca24400e85649da84d3da62b2560ed03c067573e6 languageName: node linkType: hard @@ -3312,13 +3377,6 @@ __metadata: languageName: node linkType: hard -"merge-stream@npm:^2.0.0": - version: 2.0.0 - resolution: "merge-stream@npm:2.0.0" - checksum: 10/6fa4dcc8d86629705cea944a4b88ef4cb0e07656ebf223fa287443256414283dd25d91c1cd84c77987f2aec5927af1a9db6085757cb43d90eb170ebf4b47f4f4 - languageName: node - linkType: hard - "merge2@npm:^1.3.0, merge2@npm:^1.4.1": version: 1.4.1 resolution: "merge2@npm:1.4.1" @@ -3359,20 +3417,6 @@ __metadata: languageName: node linkType: hard -"mimic-fn@npm:^2.1.0": - version: 2.1.0 - resolution: "mimic-fn@npm:2.1.0" - checksum: 10/d2421a3444848ce7f84bd49115ddacff29c15745db73f54041edc906c14b131a38d05298dae3081667627a59b2eb1ca4b436ff2e1b80f69679522410418b478a - languageName: node - linkType: hard - -"mimic-fn@npm:^4.0.0": - version: 4.0.0 - resolution: "mimic-fn@npm:4.0.0" - checksum: 10/995dcece15ee29aa16e188de6633d43a3db4611bcf93620e7e62109ec41c79c0f34277165b8ce5e361205049766e371851264c21ac64ca35499acb5421c2ba56 - languageName: node - linkType: hard - "minimatch@npm:9.0.3": version: 9.0.3 resolution: "minimatch@npm:9.0.3" @@ -3493,18 +3537,6 @@ __metadata: languageName: node linkType: hard -"mlly@npm:^1.4.2, mlly@npm:^1.7.1": - version: 1.7.1 - resolution: "mlly@npm:1.7.1" - dependencies: - acorn: "npm:^8.11.3" - pathe: "npm:^1.1.2" - pkg-types: "npm:^1.1.1" - ufo: "npm:^1.5.3" - checksum: 10/c1ef3989e95fb6c6c27a238330897b01f46507020501f45a681f2cae453f982e38dcb0e45aa65f672ea7280945d4a729d266f17a8acb187956f312b0cafddf61 - languageName: node - linkType: hard - "ms@npm:^2.1.3": version: 2.1.3 resolution: "ms@npm:2.1.3" @@ -3540,9 +3572,9 @@ __metadata: linkType: hard "negotiator@npm:^0.6.3": - version: 0.6.3 - resolution: "negotiator@npm:0.6.3" - checksum: 10/2723fb822a17ad55c93a588a4bc44d53b22855bf4be5499916ca0cab1e7165409d0b288ba2577d7b029f10ce18cf2ed8e703e5af31c984e1e2304277ef979837 + version: 0.6.4 + resolution: "negotiator@npm:0.6.4" + checksum: 10/d98c04a136583afd055746168f1067d58ce4bfe6e4c73ca1d339567f81ea1f7e665b5bd1e81f4771c67b6c2ea89b21cb2adaea2b16058c7dc31317778f931dab languageName: node linkType: hard @@ -3584,31 +3616,6 @@ __metadata: languageName: node linkType: hard -"normalize-path@npm:^3.0.0, normalize-path@npm:~3.0.0": - version: 3.0.0 - resolution: "normalize-path@npm:3.0.0" - checksum: 10/88eeb4da891e10b1318c4b2476b6e2ecbeb5ff97d946815ffea7794c31a89017c70d7f34b3c2ebf23ef4e9fc9fb99f7dffe36da22011b5b5c6ffa34f4873ec20 - languageName: node - linkType: hard - -"npm-run-path@npm:^4.0.1": - version: 4.0.1 - resolution: "npm-run-path@npm:4.0.1" - dependencies: - path-key: "npm:^3.0.0" - checksum: 10/5374c0cea4b0bbfdfae62da7bbdf1e1558d338335f4cacf2515c282ff358ff27b2ecb91ffa5330a8b14390ac66a1e146e10700440c1ab868208430f56b5f4d23 - languageName: node - linkType: hard - -"npm-run-path@npm:^5.1.0": - version: 5.3.0 - resolution: "npm-run-path@npm:5.3.0" - dependencies: - path-key: "npm:^4.0.0" - checksum: 10/ae8e7a89da9594fb9c308f6555c73f618152340dcaae423e5fb3620026fefbec463618a8b761920382d666fa7a2d8d240b6fe320e8a6cdd54dc3687e2b659d25 - languageName: node - linkType: hard - "object-assign@npm:^4.0.1, object-assign@npm:^4.1.1": version: 4.1.1 resolution: "object-assign@npm:4.1.1" @@ -3616,10 +3623,10 @@ __metadata: languageName: node linkType: hard -"object-inspect@npm:^1.13.1": - version: 1.13.2 - resolution: "object-inspect@npm:1.13.2" - checksum: 10/7ef65583b6397570a17c56f0c1841e0920e83900f2c94638927abb7b81ac08a19c7aae135bd9dcca96208cac0c7332b4650fb927f027b0cf92d71df2990d0561 +"object-inspect@npm:^1.13.1, object-inspect@npm:^1.13.3": + version: 1.13.3 + resolution: "object-inspect@npm:1.13.3" + checksum: 10/14cb973d8381c69e14d7f1c8c75044eb4caf04c6dabcf40ca5c2ce42dc2073ae0bb2a9939eeca142b0c05215afaa1cd5534adb7c8879c32cba2576e045ed8368 languageName: node linkType: hard @@ -3695,24 +3702,6 @@ __metadata: languageName: node linkType: hard -"onetime@npm:^5.1.2": - version: 5.1.2 - resolution: "onetime@npm:5.1.2" - dependencies: - mimic-fn: "npm:^2.1.0" - checksum: 10/e9fd0695a01cf226652f0385bf16b7a24153dbbb2039f764c8ba6d2306a8506b0e4ce570de6ad99c7a6eb49520743afdb66edd95ee979c1a342554ed49a9aadd - languageName: node - linkType: hard - -"onetime@npm:^6.0.0": - version: 6.0.0 - resolution: "onetime@npm:6.0.0" - dependencies: - mimic-fn: "npm:^4.0.0" - checksum: 10/0846ce78e440841335d4e9182ef69d5762e9f38aa7499b19f42ea1c4cd40f0b4446094c455c713f9adac3f4ae86f613bb5e30c99e52652764d06a89f709b3788 - languageName: node - linkType: hard - "optionator@npm:^0.9.3": version: 0.9.4 resolution: "optionator@npm:0.9.4" @@ -3736,15 +3725,6 @@ __metadata: languageName: node linkType: hard -"p-limit@npm:^5.0.0": - version: 5.0.0 - resolution: "p-limit@npm:5.0.0" - dependencies: - yocto-queue: "npm:^1.0.0" - checksum: 10/87bf5837dee6942f0dbeff318436179931d9a97848d1b07dbd86140a477a5d2e6b90d9701b210b4e21fe7beaea2979dfde366e4f576fa644a59bd4d6a6371da7 - languageName: node - linkType: hard - "p-locate@npm:^5.0.0": version: 5.0.0 resolution: "p-locate@npm:5.0.0" @@ -3764,9 +3744,9 @@ __metadata: linkType: hard "package-json-from-dist@npm:^1.0.0": - version: 1.0.0 - resolution: "package-json-from-dist@npm:1.0.0" - checksum: 10/ac706ec856a5a03f5261e4e48fa974f24feb044d51f84f8332e2af0af04fbdbdd5bbbfb9cbbe354190409bc8307c83a9e38c6672c3c8855f709afb0006a009ea + version: 1.0.1 + resolution: "package-json-from-dist@npm:1.0.1" + checksum: 10/58ee9538f2f762988433da00e26acc788036914d57c71c246bf0be1b60cdbd77dd60b6a3e1a30465f0b248aeb80079e0b34cb6050b1dfa18c06953bb1cbc7602 languageName: node linkType: hard @@ -3780,11 +3760,11 @@ __metadata: linkType: hard "parse5@npm:^7.1.2": - version: 7.1.2 - resolution: "parse5@npm:7.1.2" + version: 7.2.1 + resolution: "parse5@npm:7.2.1" dependencies: - entities: "npm:^4.4.0" - checksum: 10/3c86806bb0fb1e9a999ff3a4c883b1ca243d99f45a619a0898dbf021a95a0189ed955c31b07fe49d342b54e814f33f2c9d7489198e8630dacd5477d413ec5782 + entities: "npm:^4.5.0" + checksum: 10/fd1a8ad1540d871e1ad6ca9bf5b67e30280886f1ce4a28052c0cb885723aa984d8cb1ec3da998349a6146960c8a84aa87b1a42600eb3b94495c7303476f2f88e languageName: node linkType: hard @@ -3802,20 +3782,13 @@ __metadata: languageName: node linkType: hard -"path-key@npm:^3.0.0, path-key@npm:^3.1.0": +"path-key@npm:^3.1.0": version: 3.1.1 resolution: "path-key@npm:3.1.1" checksum: 10/55cd7a9dd4b343412a8386a743f9c746ef196e57c823d90ca3ab917f90ab9f13dd0ded27252ba49dbdfcab2b091d998bc446f6220cd3cea65db407502a740020 languageName: node linkType: hard -"path-key@npm:^4.0.0": - version: 4.0.0 - resolution: "path-key@npm:4.0.0" - checksum: 10/8e6c314ae6d16b83e93032c61020129f6f4484590a777eed709c4a01b50e498822b00f76ceaf94bc64dbd90b327df56ceadce27da3d83393790f1219e07721d7 - languageName: node - linkType: hard - "path-parse@npm:^1.0.7": version: 1.0.7 resolution: "path-parse@npm:1.0.7" @@ -3840,34 +3813,41 @@ __metadata: languageName: node linkType: hard -"pathe@npm:^1.1.1, pathe@npm:^1.1.2": +"pathe@npm:^1.1.2": version: 1.1.2 resolution: "pathe@npm:1.1.2" checksum: 10/f201d796351bf7433d147b92c20eb154a4e0ea83512017bf4ec4e492a5d6e738fb45798be4259a61aa81270179fce11026f6ff0d3fa04173041de044defe9d80 languageName: node linkType: hard -"pathval@npm:^1.1.1": - version: 1.1.1 - resolution: "pathval@npm:1.1.1" - checksum: 10/b50a4751068aa3a5428f5a0b480deecedc6f537666a3630a0c2ae2d5e7c0f4bf0ee77b48404441ec1220bef0c91625e6030b3d3cf5a32ab0d9764018d1d9dbb6 +"pathval@npm:^2.0.0": + version: 2.0.0 + resolution: "pathval@npm:2.0.0" + checksum: 10/b91575bf9cdf01757afd7b5e521eb8a0b874a49bc972d08e0047cfea0cd3c019f5614521d4bc83d2855e3fcc331db6817dfd533dd8f3d90b16bc76fad2450fc1 languageName: node linkType: hard -"picocolors@npm:^1.0.0, picocolors@npm:^1.0.1": - version: 1.1.0 - resolution: "picocolors@npm:1.1.0" - checksum: 10/a2ad60d94d185c30f2a140b19c512547713fb89b920d32cc6cf658fa786d63a37ba7b8451872c3d9fc34883971fb6e5878e07a20b60506e0bb2554dce9169ccb +"picocolors@npm:^1.0.0, picocolors@npm:^1.1.1": + version: 1.1.1 + resolution: "picocolors@npm:1.1.1" + checksum: 10/e1cf46bf84886c79055fdfa9dcb3e4711ad259949e3565154b004b260cd356c5d54b31a1437ce9782624bf766272fe6b0154f5f0c744fb7af5d454d2b60db045 languageName: node linkType: hard -"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.3.1": +"picomatch@npm:^2.3.1": version: 2.3.1 resolution: "picomatch@npm:2.3.1" checksum: 10/60c2595003b05e4535394d1da94850f5372c9427ca4413b71210f437f7b2ca091dbd611c45e8b37d10036fa8eade25c1b8951654f9d3973bfa66a2ff4d3b08bc languageName: node linkType: hard +"picomatch@npm:^4.0.2": + version: 4.0.2 + resolution: "picomatch@npm:4.0.2" + checksum: 10/ce617b8da36797d09c0baacb96ca8a44460452c89362d7cb8f70ca46b4158ba8bc3606912de7c818eb4a939f7f9015cef3c766ec8a0c6bfc725fdc078e39c717 + languageName: node + linkType: hard + "pirates@npm:^4.0.1": version: 4.0.6 resolution: "pirates@npm:4.0.6" @@ -3875,17 +3855,6 @@ __metadata: languageName: node linkType: hard -"pkg-types@npm:^1.0.3, pkg-types@npm:^1.1.1": - version: 1.2.0 - resolution: "pkg-types@npm:1.2.0" - dependencies: - confbox: "npm:^0.1.7" - mlly: "npm:^1.7.1" - pathe: "npm:^1.1.2" - checksum: 10/ed732842b86260395b82e31afc0dd8316e74642a78754ad148a5500ca5537565c6dfbd6c80c2dc92077afc1beb471b05a85a9572089cc8a1bba82248c331bf45 - languageName: node - linkType: hard - "possible-typed-array-names@npm:^1.0.0": version: 1.0.0 resolution: "possible-typed-array-names@npm:1.0.0" @@ -3917,13 +3886,13 @@ __metadata: linkType: hard "postcss@npm:^8.4.43": - version: 8.4.45 - resolution: "postcss@npm:8.4.45" + version: 8.4.49 + resolution: "postcss@npm:8.4.49" dependencies: nanoid: "npm:^3.3.7" - picocolors: "npm:^1.0.1" - source-map-js: "npm:^1.2.0" - checksum: 10/7eaf7346d04929ee979548ece5e34d253eae6f175346e298b2c4621ad6f4ee00adfe7abe72688640e910c0361ae50537c5dda3e35fd1066491282c342b3ee5c8 + picocolors: "npm:^1.1.1" + source-map-js: "npm:^1.2.1" + checksum: 10/28fe1005b1339870e0a5006375ba5ac1213fd69800f79e7db09c398e074421ba6e162898e94f64942fed554037fd292db3811d87835d25ab5ef7f3c9daacb6ca languageName: node linkType: hard @@ -3954,17 +3923,6 @@ __metadata: languageName: node linkType: hard -"pretty-format@npm:^29.7.0": - version: 29.7.0 - resolution: "pretty-format@npm:29.7.0" - dependencies: - "@jest/schemas": "npm:^29.6.3" - ansi-styles: "npm:^5.0.0" - react-is: "npm:^18.0.0" - checksum: 10/dea96bc83c83cd91b2bfc55757b6b2747edcaac45b568e46de29deee80742f17bc76fe8898135a70d904f4928eafd8bb693cd1da4896e8bdd3c5e82cadf1d2bb - languageName: node - linkType: hard - "proc-log@npm:^4.1.0, proc-log@npm:^4.2.0": version: 4.2.0 resolution: "proc-log@npm:4.2.0" @@ -3994,9 +3952,11 @@ __metadata: linkType: hard "psl@npm:^1.1.33": - version: 1.9.0 - resolution: "psl@npm:1.9.0" - checksum: 10/d07879d4bfd0ac74796306a8e5a36a93cfb9c4f4e8ee8e63fbb909066c192fe1008cd8f12abd8ba2f62ca28247949a20c8fb32e1d18831d9e71285a1569720f9 + version: 1.10.0 + resolution: "psl@npm:1.10.0" + dependencies: + punycode: "npm:^2.3.1" + checksum: 10/17b493648cc16e32c41681a4648db0c7235fbe83c78b0789b519aaccd1240fe739f9a5f4c4b55cb9e3094190ddf16e38f34f5ada179d518593ded42c957bdd8b languageName: node linkType: hard @@ -4047,13 +4007,6 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^18.0.0": - version: 18.3.1 - resolution: "react-is@npm:18.3.1" - checksum: 10/d5f60c87d285af24b1e1e7eaeb123ec256c3c8bdea7061ab3932e3e14685708221bf234ec50b21e10dd07f008f1b966a2730a0ce4ff67905b3872ff2042aec22 - languageName: node - linkType: hard - "react-redux@npm:^9.0.4": version: 9.1.2 resolution: "react-redux@npm:9.1.2" @@ -4093,12 +4046,10 @@ __metadata: languageName: node linkType: hard -"readdirp@npm:~3.6.0": - version: 3.6.0 - resolution: "readdirp@npm:3.6.0" - dependencies: - picomatch: "npm:^2.2.1" - checksum: 10/196b30ef6ccf9b6e18c4e1724b7334f72a093d011a99f3b5920470f0b3406a51770867b3e1ae9711f227ef7a7065982f6ee2ce316746b2cb42c88efe44297fe7 +"readdirp@npm:^4.0.1": + version: 4.0.2 + resolution: "readdirp@npm:4.0.2" + checksum: 10/4ef93103307c7d5e42e78ecf201db58c984c4d66882a27c956250478b49c2444b1ff6aea8ce0f5e4157b2c07ce2fe870ad16c92ebd7c6ff30391ded6e42b9873 languageName: node linkType: hard @@ -4149,15 +4100,15 @@ __metadata: languageName: node linkType: hard -"regexp.prototype.flags@npm:^1.5.1, regexp.prototype.flags@npm:^1.5.2": - version: 1.5.2 - resolution: "regexp.prototype.flags@npm:1.5.2" +"regexp.prototype.flags@npm:^1.5.1, regexp.prototype.flags@npm:^1.5.2, regexp.prototype.flags@npm:^1.5.3": + version: 1.5.3 + resolution: "regexp.prototype.flags@npm:1.5.3" dependencies: - call-bind: "npm:^1.0.6" + call-bind: "npm:^1.0.7" define-properties: "npm:^1.2.1" es-errors: "npm:^1.3.0" - set-function-name: "npm:^2.0.1" - checksum: 10/9fffc01da9c4e12670ff95bc5204364615fcc12d86fc30642765af908675678ebb0780883c874b2dbd184505fb52fa603d80073ecf69f461ce7f56b15d10be9c + set-function-name: "npm:^2.0.2" + checksum: 10/fe17bc4eebbc72945aaf9dd059eb7784a5ca453a67cc4b5b3e399ab08452c9a05befd92063e2c52e7b24d9238c60031656af32dd57c555d1ba6330dbf8c23b43 languageName: node linkType: hard @@ -4203,6 +4154,7 @@ __metadata: "@reduxjs/toolkit": "npm:^2.0.1" "@testing-library/react": "npm:^14.1.2" "@types/lodash": "npm:^4.14.175" + "@types/node": "npm:^22.9.0" "@types/react": "npm:^18.2.38" "@types/react-dom": "npm:^18.2.17" "@types/shelljs": "npm:^0.8.11" @@ -4227,7 +4179,7 @@ __metadata: shelljs: "npm:^0.8.5" tsup: "npm:^8.2.4" typescript: "npm:^5.4.2" - vitest: "npm:^1.6.0" + vitest: "npm:^2.1.5" languageName: unknown linkType: soft @@ -4322,27 +4274,29 @@ __metadata: languageName: node linkType: hard -"rollup@npm:^4.19.0, rollup@npm:^4.20.0": - version: 4.21.3 - resolution: "rollup@npm:4.21.3" - dependencies: - "@rollup/rollup-android-arm-eabi": "npm:4.21.3" - "@rollup/rollup-android-arm64": "npm:4.21.3" - "@rollup/rollup-darwin-arm64": "npm:4.21.3" - "@rollup/rollup-darwin-x64": "npm:4.21.3" - "@rollup/rollup-linux-arm-gnueabihf": "npm:4.21.3" - "@rollup/rollup-linux-arm-musleabihf": "npm:4.21.3" - "@rollup/rollup-linux-arm64-gnu": "npm:4.21.3" - "@rollup/rollup-linux-arm64-musl": "npm:4.21.3" - "@rollup/rollup-linux-powerpc64le-gnu": "npm:4.21.3" - "@rollup/rollup-linux-riscv64-gnu": "npm:4.21.3" - "@rollup/rollup-linux-s390x-gnu": "npm:4.21.3" - "@rollup/rollup-linux-x64-gnu": "npm:4.21.3" - "@rollup/rollup-linux-x64-musl": "npm:4.21.3" - "@rollup/rollup-win32-arm64-msvc": "npm:4.21.3" - "@rollup/rollup-win32-ia32-msvc": "npm:4.21.3" - "@rollup/rollup-win32-x64-msvc": "npm:4.21.3" - "@types/estree": "npm:1.0.5" +"rollup@npm:^4.20.0, rollup@npm:^4.24.0": + version: 4.26.0 + resolution: "rollup@npm:4.26.0" + dependencies: + "@rollup/rollup-android-arm-eabi": "npm:4.26.0" + "@rollup/rollup-android-arm64": "npm:4.26.0" + "@rollup/rollup-darwin-arm64": "npm:4.26.0" + "@rollup/rollup-darwin-x64": "npm:4.26.0" + "@rollup/rollup-freebsd-arm64": "npm:4.26.0" + "@rollup/rollup-freebsd-x64": "npm:4.26.0" + "@rollup/rollup-linux-arm-gnueabihf": "npm:4.26.0" + "@rollup/rollup-linux-arm-musleabihf": "npm:4.26.0" + "@rollup/rollup-linux-arm64-gnu": "npm:4.26.0" + "@rollup/rollup-linux-arm64-musl": "npm:4.26.0" + "@rollup/rollup-linux-powerpc64le-gnu": "npm:4.26.0" + "@rollup/rollup-linux-riscv64-gnu": "npm:4.26.0" + "@rollup/rollup-linux-s390x-gnu": "npm:4.26.0" + "@rollup/rollup-linux-x64-gnu": "npm:4.26.0" + "@rollup/rollup-linux-x64-musl": "npm:4.26.0" + "@rollup/rollup-win32-arm64-msvc": "npm:4.26.0" + "@rollup/rollup-win32-ia32-msvc": "npm:4.26.0" + "@rollup/rollup-win32-x64-msvc": "npm:4.26.0" + "@types/estree": "npm:1.0.6" fsevents: "npm:~2.3.2" dependenciesMeta: "@rollup/rollup-android-arm-eabi": @@ -4353,6 +4307,10 @@ __metadata: optional: true "@rollup/rollup-darwin-x64": optional: true + "@rollup/rollup-freebsd-arm64": + optional: true + "@rollup/rollup-freebsd-x64": + optional: true "@rollup/rollup-linux-arm-gnueabihf": optional: true "@rollup/rollup-linux-arm-musleabihf": @@ -4381,7 +4339,7 @@ __metadata: optional: true bin: rollup: dist/bin/rollup - checksum: 10/60a1d6548fa1e612209f9f98f83c73a213f27569abddcbfb246af08455d730f367d95f6bd541b58c9e1e643c181463db27326c712aa81efd4071372a4d3481b9 + checksum: 10/aec4d876617298400c0c03d35fed67e5193addc82a76f2b2a2f4c2b000cafbca84a33cf2e686dea1d1caa06fe4028dd94b8e6cd1f5bc3bbd19026a188bb2ec55 languageName: node linkType: hard @@ -4555,14 +4513,7 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:^3.0.3": - version: 3.0.7 - resolution: "signal-exit@npm:3.0.7" - checksum: 10/a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 - languageName: node - linkType: hard - -"signal-exit@npm:^4.0.1, signal-exit@npm:^4.1.0": +"signal-exit@npm:^4.0.1": version: 4.1.0 resolution: "signal-exit@npm:4.1.0" checksum: 10/c9fa63bbbd7431066174a48ba2dd9986dfd930c3a8b59de9c29d7b6854ec1c12a80d15310869ea5166d413b99f041bfa3dd80a7947bcd44ea8e6eb3ffeabfa1f @@ -4604,7 +4555,7 @@ __metadata: languageName: node linkType: hard -"source-map-js@npm:^1.0.1, source-map-js@npm:^1.2.0": +"source-map-js@npm:^1.0.1, source-map-js@npm:^1.2.1": version: 1.2.1 resolution: "source-map-js@npm:1.2.1" checksum: 10/ff9d8c8bf096d534a5b7707e0382ef827b4dd360a577d3f34d2b9f48e12c9d230b5747974ee7c607f0df65113732711bb701fe9ece3c7edbd43cb2294d707df3 @@ -4652,10 +4603,10 @@ __metadata: languageName: node linkType: hard -"std-env@npm:^3.5.0": - version: 3.7.0 - resolution: "std-env@npm:3.7.0" - checksum: 10/6ee0cca1add3fd84656b0002cfbc5bfa20340389d9ba4720569840f1caa34bce74322aef4c93f046391583e50649d0cf81a5f8fe1d411e50b659571690a45f12 +"std-env@npm:^3.8.0": + version: 3.8.0 + resolution: "std-env@npm:3.8.0" + checksum: 10/034176196cfcaaab16dbdd96fc9e925a9544799fb6dc5a3e36fe43270f3a287c7f779d785b89edaf22cef2b5f1dcada2aae67430b8602e785ee74bdb3f671768 languageName: node linkType: hard @@ -4781,20 +4732,6 @@ __metadata: languageName: node linkType: hard -"strip-final-newline@npm:^2.0.0": - version: 2.0.0 - resolution: "strip-final-newline@npm:2.0.0" - checksum: 10/69412b5e25731e1938184b5d489c32e340605bb611d6140344abc3421b7f3c6f9984b21dff296dfcf056681b82caa3bb4cc996a965ce37bcfad663e92eae9c64 - languageName: node - linkType: hard - -"strip-final-newline@npm:^3.0.0": - version: 3.0.0 - resolution: "strip-final-newline@npm:3.0.0" - checksum: 10/23ee263adfa2070cd0f23d1ac14e2ed2f000c9b44229aec9c799f1367ec001478469560abefd00c5c99ee6f0b31c137d53ec6029c53e9f32a93804e18c201050 - languageName: node - linkType: hard - "strip-json-comments@npm:^3.1.1": version: 3.1.1 resolution: "strip-json-comments@npm:3.1.1" @@ -4802,15 +4739,6 @@ __metadata: languageName: node linkType: hard -"strip-literal@npm:^2.0.0": - version: 2.1.0 - resolution: "strip-literal@npm:2.1.0" - dependencies: - js-tokens: "npm:^9.0.0" - checksum: 10/21c813aa1e669944e7e2318c8c927939fb90b0c52f53f57282bfc3dd6e19d53f70004f1f1693e33e5e790ad5ef102b0fce2b243808229d1ce07ae71f326c0e82 - languageName: node - linkType: hard - "sucrase@npm:^3.35.0": version: 3.35.0 resolution: "sucrase@npm:3.35.0" @@ -4829,15 +4757,6 @@ __metadata: languageName: node linkType: hard -"supports-color@npm:^5.3.0": - version: 5.5.0 - resolution: "supports-color@npm:5.5.0" - dependencies: - has-flag: "npm:^3.0.0" - checksum: 10/5f505c6fa3c6e05873b43af096ddeb22159831597649881aeb8572d6fe3b81e798cc10840d0c9735e0026b250368851b7f77b65e84f4e4daa820a4f69947f55b - languageName: node - linkType: hard - "supports-color@npm:^7.1.0": version: 7.2.0 resolution: "supports-color@npm:7.2.0" @@ -4909,24 +4828,48 @@ __metadata: languageName: node linkType: hard -"tinybench@npm:^2.5.1": +"tinybench@npm:^2.9.0": version: 2.9.0 resolution: "tinybench@npm:2.9.0" checksum: 10/cfa1e1418e91289219501703c4693c70708c91ffb7f040fd318d24aef419fb5a43e0c0160df9471499191968b2451d8da7f8087b08c3133c251c40d24aced06c languageName: node linkType: hard -"tinypool@npm:^0.8.3": - version: 0.8.4 - resolution: "tinypool@npm:0.8.4" - checksum: 10/7365944c2532f240111443e7012be31a634faf1a02db08a91db3aa07361c26a374d0be00a0f2ea052c4bee39c107ba67f1f814c108d9d51dfc725c559c1a9c03 +"tinyexec@npm:^0.3.1": + version: 0.3.1 + resolution: "tinyexec@npm:0.3.1" + checksum: 10/0537c70590d52d354f40c0255ff0f654a3d18ddb3812b440ddf9d436edf516c8057838ad5a38744c0c59670ec03e3cf23fbe04ae3d49f031d948274e99002569 languageName: node linkType: hard -"tinyspy@npm:^2.2.0": - version: 2.2.1 - resolution: "tinyspy@npm:2.2.1" - checksum: 10/170d6232e87f9044f537b50b406a38fbfd6f79a261cd12b92879947bd340939a833a678632ce4f5c4a6feab4477e9c21cd43faac3b90b68b77dd0536c4149736 +"tinyglobby@npm:^0.2.9": + version: 0.2.10 + resolution: "tinyglobby@npm:0.2.10" + dependencies: + fdir: "npm:^6.4.2" + picomatch: "npm:^4.0.2" + checksum: 10/10c976866d849702edc47fc3fef27d63f074c40f75ef17171ecc1452967900699fa1e62373681dd58e673ddff2e3f6094bcd0a2101e3e4b30f4c2b9da41397f2 + languageName: node + linkType: hard + +"tinypool@npm:^1.0.1": + version: 1.0.1 + resolution: "tinypool@npm:1.0.1" + checksum: 10/eaceb93784b8e27e60c0e3e2c7d11c29e1e79b2a025b2c232215db73b90fe22bd4753ad53fc8e801c2b5a63b94a823af549555d8361272bc98271de7dd4a9925 + languageName: node + linkType: hard + +"tinyrainbow@npm:^1.2.0": + version: 1.2.0 + resolution: "tinyrainbow@npm:1.2.0" + checksum: 10/2924444db6804355e5ba2b6e586c7f77329d93abdd7257a069a0f4530dff9f16de484e80479094e3f39273462541b003a65ee3a6afc2d12555aa745132deba5d + languageName: node + linkType: hard + +"tinyspy@npm:^3.0.2": + version: 3.0.2 + resolution: "tinyspy@npm:3.0.2" + checksum: 10/5db671b2ff5cd309de650c8c4761ca945459d7204afb1776db9a04fb4efa28a75f08517a8620c01ee32a577748802231ad92f7d5b194dc003ee7f987a2a06337 languageName: node linkType: hard @@ -4986,11 +4929,11 @@ __metadata: linkType: hard "ts-api-utils@npm:^1.0.1": - version: 1.3.0 - resolution: "ts-api-utils@npm:1.3.0" + version: 1.4.0 + resolution: "ts-api-utils@npm:1.4.0" peerDependencies: typescript: ">=4.2.0" - checksum: 10/3ee44faa24410cd649b5c864e068d438aa437ef64e9e4a66a41646a6d3024d3097a695eeb3fb26ee364705d3cb9653a65756d009e6a53badb6066a5f447bf7ed + checksum: 10/b2020d5da55e28dc9dd32fb94730a4f6caefbd8e103029b6b6de5f15d18873067d734f64761c424c78ad1393a2b99d82b5a9fd34d663c12243acca7d3439090b languageName: node linkType: hard @@ -5002,24 +4945,24 @@ __metadata: linkType: hard "tsup@npm:^8.2.4": - version: 8.2.4 - resolution: "tsup@npm:8.2.4" + version: 8.3.5 + resolution: "tsup@npm:8.3.5" dependencies: bundle-require: "npm:^5.0.0" cac: "npm:^6.7.14" - chokidar: "npm:^3.6.0" + chokidar: "npm:^4.0.1" consola: "npm:^3.2.3" - debug: "npm:^4.3.5" - esbuild: "npm:^0.23.0" - execa: "npm:^5.1.1" - globby: "npm:^11.1.0" + debug: "npm:^4.3.7" + esbuild: "npm:^0.24.0" joycon: "npm:^3.1.1" - picocolors: "npm:^1.0.1" + picocolors: "npm:^1.1.1" postcss-load-config: "npm:^6.0.1" resolve-from: "npm:^5.0.0" - rollup: "npm:^4.19.0" + rollup: "npm:^4.24.0" source-map: "npm:0.8.0-beta.0" sucrase: "npm:^3.35.0" + tinyexec: "npm:^0.3.1" + tinyglobby: "npm:^0.2.9" tree-kill: "npm:^1.2.2" peerDependencies: "@microsoft/api-extractor": ^7.36.0 @@ -5038,7 +4981,7 @@ __metadata: bin: tsup: dist/cli-default.js tsup-node: dist/cli-node.js - checksum: 10/89613c3490797f7e107c55f961e2681d455b45a3acfe567dd3825d7ccd14b91f3cf8462f389b6e5ed7e9dd96266adc60830256d52f1bd5d443a1db504c9a7912 + checksum: 10/8cf694d5fe7923c47273388f7fb203fe64fe66efb65a96829d361de3360d4db4299e7f82f4e6354716b580c9a1eadb336a25759f90fdc61fe816d5d7d9a28003 languageName: node linkType: hard @@ -5051,13 +4994,6 @@ __metadata: languageName: node linkType: hard -"type-detect@npm:^4.0.0, type-detect@npm:^4.1.0": - version: 4.1.0 - resolution: "type-detect@npm:4.1.0" - checksum: 10/e363bf0352427a79301f26a7795a27718624c49c576965076624eb5495d87515030b207217845f7018093adcbe169b2d119bb9b7f1a31a92bfbb1ab9639ca8dd - languageName: node - linkType: hard - "type-fest@npm:^0.20.2": version: 0.20.2 resolution: "type-fest@npm:0.20.2" @@ -5118,29 +5054,22 @@ __metadata: linkType: hard "typescript@npm:^5.4.2": - version: 5.6.2 - resolution: "typescript@npm:5.6.2" + version: 5.6.3 + resolution: "typescript@npm:5.6.3" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10/f95365d4898f357823e93d334ecda9fcade54f009b397c7d05b7621cd9e865981033cf89ccde0f3e3a7b73b1fdbae18e92bc77db237b43e912f053fef0f9a53b + checksum: 10/c328e418e124b500908781d9f7b9b93cf08b66bf5936d94332b463822eea2f4e62973bfb3b8a745fdc038785cb66cf59d1092bac3ec2ac6a3e5854687f7833f1 languageName: node linkType: hard "typescript@patch:typescript@npm%3A^5.4.2#optional!builtin": - version: 5.6.2 - resolution: "typescript@patch:typescript@npm%3A5.6.2#optional!builtin::version=5.6.2&hash=8c6c40" + version: 5.6.3 + resolution: "typescript@patch:typescript@npm%3A5.6.3#optional!builtin::version=5.6.3&hash=8c6c40" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10/8bfc7ca0d9feca4c3fcbd6c70741abfcd714197d6448e68225ae71e462447d904d3bfba49759a8fbe4956d87f054e2d346833c8349c222daa594a2626d4e1be8 - languageName: node - linkType: hard - -"ufo@npm:^1.5.3": - version: 1.5.4 - resolution: "ufo@npm:1.5.4" - checksum: 10/a885ed421e656aea6ca64e9727b8118a9488715460b6f1a0f0427118adfe2f2830fe7c1d5bd9c5c754a332e6807516551cd663ea67ce9ed6a4e3edc739916335 + checksum: 10/00504c01ee42d470c23495426af07512e25e6546bce7e24572e72a9ca2e6b2e9bea63de4286c3cfea644874da1467dcfca23f4f98f7caf20f8b03c0213bb6837 languageName: node linkType: hard @@ -5156,7 +5085,7 @@ __metadata: languageName: node linkType: hard -"undici-types@npm:~6.19.2": +"undici-types@npm:~6.19.8": version: 6.19.8 resolution: "undici-types@npm:6.19.8" checksum: 10/cf0b48ed4fc99baf56584afa91aaffa5010c268b8842f62e02f752df209e3dea138b372a60a963b3b2576ed932f32329ce7ddb9cb5f27a6c83040d8cd74b7a70 @@ -5223,24 +5152,24 @@ __metadata: languageName: node linkType: hard -"vite-node@npm:1.6.0": - version: 1.6.0 - resolution: "vite-node@npm:1.6.0" +"vite-node@npm:2.1.5": + version: 2.1.5 + resolution: "vite-node@npm:2.1.5" dependencies: cac: "npm:^6.7.14" - debug: "npm:^4.3.4" - pathe: "npm:^1.1.1" - picocolors: "npm:^1.0.0" + debug: "npm:^4.3.7" + es-module-lexer: "npm:^1.5.4" + pathe: "npm:^1.1.2" vite: "npm:^5.0.0" bin: vite-node: vite-node.mjs - checksum: 10/40230598c3c285cf65f407ac50b1c7753ab2dfa960de76ec1a95a0ce0ff963919d065c29ba538d9fb2fba3e0703a051d49d1ad6486001ba2f90616cc706ddc3d + checksum: 10/53d90523bf114dce26d5f66aa01aa05c33d33c7b87e8129b8a7f1c0d5014a9922f61feb9df01b54c1f851214604f7e8d2ff58ca257d3bf28539eafa8e8d72b81 languageName: node linkType: hard "vite@npm:^5.0.0": - version: 5.4.4 - resolution: "vite@npm:5.4.4" + version: 5.4.11 + resolution: "vite@npm:5.4.11" dependencies: esbuild: "npm:^0.21.3" fsevents: "npm:~2.3.3" @@ -5277,39 +5206,39 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: 10/8c2ded5cc99464362d35af6b78bd6466b9c36533a26311d360c327d0a1580d0016f4f3c4828ded5945be4adc2990f257eae85ff95b4522a6d040cdfef6e5f7b2 + checksum: 10/719c4dea896e9547958643354003c8c9ea98e5367196d98f5f46cffb3ec963fead3ea5853f5af941c79bbfb73583dec19bbb0d28d2f644b95d7f59c55e22919d languageName: node linkType: hard -"vitest@npm:^1.6.0": - version: 1.6.0 - resolution: "vitest@npm:1.6.0" - dependencies: - "@vitest/expect": "npm:1.6.0" - "@vitest/runner": "npm:1.6.0" - "@vitest/snapshot": "npm:1.6.0" - "@vitest/spy": "npm:1.6.0" - "@vitest/utils": "npm:1.6.0" - acorn-walk: "npm:^8.3.2" - chai: "npm:^4.3.10" - debug: "npm:^4.3.4" - execa: "npm:^8.0.1" - local-pkg: "npm:^0.5.0" - magic-string: "npm:^0.30.5" - pathe: "npm:^1.1.1" - picocolors: "npm:^1.0.0" - std-env: "npm:^3.5.0" - strip-literal: "npm:^2.0.0" - tinybench: "npm:^2.5.1" - tinypool: "npm:^0.8.3" +"vitest@npm:^2.1.5": + version: 2.1.5 + resolution: "vitest@npm:2.1.5" + dependencies: + "@vitest/expect": "npm:2.1.5" + "@vitest/mocker": "npm:2.1.5" + "@vitest/pretty-format": "npm:^2.1.5" + "@vitest/runner": "npm:2.1.5" + "@vitest/snapshot": "npm:2.1.5" + "@vitest/spy": "npm:2.1.5" + "@vitest/utils": "npm:2.1.5" + chai: "npm:^5.1.2" + debug: "npm:^4.3.7" + expect-type: "npm:^1.1.0" + magic-string: "npm:^0.30.12" + pathe: "npm:^1.1.2" + std-env: "npm:^3.8.0" + tinybench: "npm:^2.9.0" + tinyexec: "npm:^0.3.1" + tinypool: "npm:^1.0.1" + tinyrainbow: "npm:^1.2.0" vite: "npm:^5.0.0" - vite-node: "npm:1.6.0" - why-is-node-running: "npm:^2.2.2" + vite-node: "npm:2.1.5" + why-is-node-running: "npm:^2.3.0" peerDependencies: "@edge-runtime/vm": "*" "@types/node": ^18.0.0 || >=20.0.0 - "@vitest/browser": 1.6.0 - "@vitest/ui": 1.6.0 + "@vitest/browser": 2.1.5 + "@vitest/ui": 2.1.5 happy-dom: "*" jsdom: "*" peerDependenciesMeta: @@ -5327,7 +5256,7 @@ __metadata: optional: true bin: vitest: vitest.mjs - checksum: 10/ad921a723ac9438636d37111f0b2ea5afd0ba4a7813fb75382b9f75574e10d533cf950573ebb9332a595ce197cb83593737a6b55a3b6e6eb00bddbcd0920a03e + checksum: 10/83e8f446bd882ccf2911c387ca89055f4565d7fb201dca9c88fae1bca2c2ea2337d7abd1e505f69b86049e396f44eaac121a88270e36bca59f9e66646fff6990 languageName: node linkType: hard @@ -5471,7 +5400,7 @@ __metadata: languageName: node linkType: hard -"why-is-node-running@npm:^2.2.2": +"why-is-node-running@npm:^2.3.0": version: 2.3.0 resolution: "why-is-node-running@npm:2.3.0" dependencies: @@ -5590,10 +5519,3 @@ __metadata: checksum: 10/f77b3d8d00310def622123df93d4ee654fc6a0096182af8bd60679ddcdfb3474c56c6c7190817c84a2785648cdee9d721c0154eb45698c62176c322fb46fc700 languageName: node linkType: hard - -"yocto-queue@npm:^1.0.0": - version: 1.1.1 - resolution: "yocto-queue@npm:1.1.1" - checksum: 10/f2e05b767ed3141e6372a80af9caa4715d60969227f38b1a4370d60bffe153c9c5b33a862905609afc9b375ec57cd40999810d20e5e10229a204e8bde7ef255c - languageName: node - linkType: hard