From 59a792674ad6df67f3828e766602f05a10ceebaf Mon Sep 17 00:00:00 2001 From: Matt Date: Sat, 5 Mar 2022 12:54:30 +0000 Subject: [PATCH 1/4] Add type parameter for Id in createEntityAdapter --- .../toolkit/src/entities/create_adapter.ts | 28 ++- packages/toolkit/src/entities/entity_state.ts | 13 +- packages/toolkit/src/entities/models.ts | 177 ++++++++++-------- .../src/entities/sorted_state_adapter.ts | 30 +-- .../toolkit/src/entities/state_adapter.ts | 22 +-- .../toolkit/src/entities/state_selectors.ts | 25 +-- .../src/entities/tests/entity_state.test.ts | 2 +- .../src/entities/tests/state_adapter.test.ts | 2 +- .../entities/tests/state_selectors.test.ts | 24 ++- .../src/entities/unsorted_state_adapter.ts | 36 ++-- packages/toolkit/src/entities/utils.ts | 21 ++- .../toolkit/src/tests/combinedTest.test.ts | 2 +- .../src/tests/createEntityAdapter.typetest.ts | 32 ++-- 13 files changed, 232 insertions(+), 182 deletions(-) diff --git a/packages/toolkit/src/entities/create_adapter.ts b/packages/toolkit/src/entities/create_adapter.ts index 0d0c77e9d1..39d97ede4f 100644 --- a/packages/toolkit/src/entities/create_adapter.ts +++ b/packages/toolkit/src/entities/create_adapter.ts @@ -3,32 +3,46 @@ import type { Comparer, IdSelector, EntityAdapter, + EntityId, } from './models' import { createInitialStateFactory } from './entity_state' import { createSelectorsFactory } from './state_selectors' import { createSortedStateAdapter } from './sorted_state_adapter' import { createUnsortedStateAdapter } from './unsorted_state_adapter' +type ExtractEntityId = T extends { id: infer Id } + ? Id + : never + +export function createEntityAdapter(options?: { + sortComparer?: false | Comparer +}): EntityAdapter> + +export function createEntityAdapter(options: { + selectId: IdSelector + sortComparer?: false | Comparer +}): EntityAdapter + /** * * @param options * * @public */ -export function createEntityAdapter( +export function createEntityAdapter( options: { - selectId?: IdSelector + selectId?: IdSelector sortComparer?: false | Comparer } = {} -): EntityAdapter { - const { selectId, sortComparer }: EntityDefinition = { +): EntityAdapter { + const { selectId, sortComparer }: EntityDefinition = { sortComparer: false, - selectId: (instance: any) => instance.id, + selectId: (instance: any) => instance.id as Id, ...options, } - const stateFactory = createInitialStateFactory() - const selectorsFactory = createSelectorsFactory() + const stateFactory = createInitialStateFactory() + const selectorsFactory = createSelectorsFactory() const stateAdapter = sortComparer ? createSortedStateAdapter(selectId, sortComparer) : createUnsortedStateAdapter(selectId) diff --git a/packages/toolkit/src/entities/entity_state.ts b/packages/toolkit/src/entities/entity_state.ts index 60924e3ae4..44a9595109 100644 --- a/packages/toolkit/src/entities/entity_state.ts +++ b/packages/toolkit/src/entities/entity_state.ts @@ -1,17 +1,20 @@ -import type { EntityState } from './models' +import type { EntityId, EntityState } from './models' -export function getInitialEntityState(): EntityState { +export function getInitialEntityState(): EntityState< + V, + Id +> { return { ids: [], entities: {}, } } -export function createInitialStateFactory() { - function getInitialState(): EntityState +export function createInitialStateFactory() { + function getInitialState(): EntityState function getInitialState( additionalState: S - ): EntityState & S + ): EntityState & S function getInitialState(additionalState: any = {}): any { return Object.assign(getInitialEntityState(), additionalState) } diff --git a/packages/toolkit/src/entities/models.ts b/packages/toolkit/src/entities/models.ts index e57c4aee9a..b6180bea70 100644 --- a/packages/toolkit/src/entities/models.ts +++ b/packages/toolkit/src/entities/models.ts @@ -14,158 +14,171 @@ export type Comparer = (a: T, b: T) => number /** * @public */ -export type IdSelector = (model: T) => EntityId +export type IdSelector = (model: T) => Id /** * @public */ -export interface DictionaryNum { - [id: number]: T | undefined -} +export type Dictionary = Partial> /** * @public */ -export interface Dictionary extends DictionaryNum { - [id: string]: T | undefined -} +export type DictionaryNum = Dictionary /** * @public */ -export type Update = { id: EntityId; changes: Partial } +export type Update = { id: Id; changes: Partial } /** * @public */ -export interface EntityState { - ids: EntityId[] - entities: Dictionary +export interface EntityState { + ids: Id[] + entities: Dictionary } /** * @public */ -export interface EntityDefinition { - selectId: IdSelector +export interface EntityDefinition { + selectId: IdSelector sortComparer: false | Comparer } -export type PreventAny = IsAny, S> +export type PreventAny = IsAny< + S, + EntityState, + S +> /** * @public */ -export interface EntityStateAdapter { - addOne>(state: PreventAny, entity: T): S - addOne>( - state: PreventAny, +export interface EntityStateAdapter { + addOne>( + state: PreventAny, + entity: T + ): S + addOne>( + state: PreventAny, action: PayloadAction ): S - addMany>( - state: PreventAny, - entities: readonly T[] | Record + addMany>( + state: PreventAny, + entities: readonly T[] | Record ): S - addMany>( - state: PreventAny, - entities: PayloadAction> + addMany>( + state: PreventAny, + entities: PayloadAction> ): S - setOne>(state: PreventAny, entity: T): S - setOne>( - state: PreventAny, + setOne>( + state: PreventAny, + entity: T + ): S + setOne>( + state: PreventAny, action: PayloadAction ): S - setMany>( - state: PreventAny, - entities: readonly T[] | Record + setMany>( + state: PreventAny, + entities: readonly T[] | Record ): S - setMany>( - state: PreventAny, - entities: PayloadAction> + setMany>( + state: PreventAny, + entities: PayloadAction> ): S - setAll>( - state: PreventAny, - entities: readonly T[] | Record + setAll>( + state: PreventAny, + entities: readonly T[] | Record ): S - setAll>( - state: PreventAny, - entities: PayloadAction> + setAll>( + state: PreventAny, + entities: PayloadAction> ): S - removeOne>(state: PreventAny, key: EntityId): S - removeOne>( - state: PreventAny, - key: PayloadAction + removeOne>( + state: PreventAny, + key: Id + ): S + removeOne>( + state: PreventAny, + key: PayloadAction ): S - removeMany>( - state: PreventAny, - keys: readonly EntityId[] + removeMany>( + state: PreventAny, + keys: readonly Id[] ): S - removeMany>( - state: PreventAny, - keys: PayloadAction + removeMany>( + state: PreventAny, + keys: PayloadAction ): S - removeAll>(state: PreventAny): S + removeAll>(state: PreventAny): S - updateOne>( - state: PreventAny, - update: Update + updateOne>( + state: PreventAny, + update: Update ): S - updateOne>( - state: PreventAny, - update: PayloadAction> + updateOne>( + state: PreventAny, + update: PayloadAction> ): S - updateMany>( - state: PreventAny, - updates: ReadonlyArray> + updateMany>( + state: PreventAny, + updates: ReadonlyArray> ): S - updateMany>( - state: PreventAny, - updates: PayloadAction>> + updateMany>( + state: PreventAny, + updates: PayloadAction>> ): S - upsertOne>(state: PreventAny, entity: T): S - upsertOne>( - state: PreventAny, + upsertOne>( + state: PreventAny, + entity: T + ): S + upsertOne>( + state: PreventAny, entity: PayloadAction ): S - upsertMany>( - state: PreventAny, - entities: readonly T[] | Record + upsertMany>( + state: PreventAny, + entities: readonly T[] | Record ): S - upsertMany>( - state: PreventAny, - entities: PayloadAction> + upsertMany>( + state: PreventAny, + entities: PayloadAction> ): S } /** * @public */ -export interface EntitySelectors { - selectIds: (state: V) => EntityId[] - selectEntities: (state: V) => Dictionary +export interface EntitySelectors { + selectIds: (state: V) => Id[] + selectEntities: (state: V) => Dictionary selectAll: (state: V) => T[] selectTotal: (state: V) => number - selectById: (state: V, id: EntityId) => T | undefined + selectById: (state: V, id: Id) => T | undefined } /** * @public */ -export interface EntityAdapter extends EntityStateAdapter { - selectId: IdSelector +export interface EntityAdapter + extends EntityStateAdapter { + selectId: IdSelector sortComparer: false | Comparer - getInitialState(): EntityState - getInitialState(state: S): EntityState & S - getSelectors(): EntitySelectors> + getInitialState(): EntityState + getInitialState(state: S): EntityState & S + getSelectors(): EntitySelectors, Id> getSelectors( - selectState: (state: V) => EntityState - ): EntitySelectors + selectState: (state: V) => EntityState + ): EntitySelectors } diff --git a/packages/toolkit/src/entities/sorted_state_adapter.ts b/packages/toolkit/src/entities/sorted_state_adapter.ts index 4812d8e575..de0d562440 100644 --- a/packages/toolkit/src/entities/sorted_state_adapter.ts +++ b/packages/toolkit/src/entities/sorted_state_adapter.ts @@ -14,11 +14,11 @@ import { splitAddedUpdatedEntities, } from './utils' -export function createSortedStateAdapter( - selectId: IdSelector, +export function createSortedStateAdapter( + selectId: IdSelector, sort: Comparer -): EntityStateAdapter { - type R = EntityState +): EntityStateAdapter { + type R = EntityState const { removeOne, removeMany, removeAll } = createUnsortedStateAdapter(selectId) @@ -28,7 +28,7 @@ export function createSortedStateAdapter( } function addManyMutably( - newEntities: readonly T[] | Record, + newEntities: readonly T[] | Record, state: R ): void { newEntities = ensureEntitiesArray(newEntities) @@ -47,7 +47,7 @@ export function createSortedStateAdapter( } function setManyMutably( - newEntities: readonly T[] | Record, + newEntities: readonly T[] | Record, state: R ): void { newEntities = ensureEntitiesArray(newEntities) @@ -57,7 +57,7 @@ export function createSortedStateAdapter( } function setAllMutably( - newEntities: readonly T[] | Record, + newEntities: readonly T[] | Record, state: R ): void { newEntities = ensureEntitiesArray(newEntities) @@ -67,17 +67,21 @@ export function createSortedStateAdapter( addManyMutably(newEntities, state) } - function updateOneMutably(update: Update, state: R): void { + function updateOneMutably(update: Update, state: R): void { return updateManyMutably([update], state) } // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types - function takeUpdatedModel(models: T[], update: Update, state: R): boolean { + function takeUpdatedModel( + models: T[], + update: Update, + state: R + ): boolean { if (!(update.id in state.entities)) { return false } - const original = state.entities[update.id] + const original: T | undefined = state.entities[update.id] const updated = Object.assign({}, original, update.changes) const newKey = selectIdValue(updated, selectId) @@ -89,7 +93,7 @@ export function createSortedStateAdapter( } function updateManyMutably( - updates: ReadonlyArray>, + updates: ReadonlyArray>, state: R ): void { const models: T[] = [] @@ -106,10 +110,10 @@ export function createSortedStateAdapter( } function upsertManyMutably( - newEntities: readonly T[] | Record, + newEntities: readonly T[] | Record, state: R ): void { - const [added, updated] = splitAddedUpdatedEntities( + const [added, updated] = splitAddedUpdatedEntities( newEntities, selectId, state diff --git a/packages/toolkit/src/entities/state_adapter.ts b/packages/toolkit/src/entities/state_adapter.ts index fbc1577683..bf7ddffeab 100644 --- a/packages/toolkit/src/entities/state_adapter.ts +++ b/packages/toolkit/src/entities/state_adapter.ts @@ -1,27 +1,27 @@ import createNextState, { isDraft } from 'immer' -import type { EntityState, PreventAny } from './models' +import type { EntityId, EntityState, PreventAny } from './models' import type { PayloadAction } from '../createAction' import { isFSA } from '../createAction' import { IsAny } from '../tsHelpers' -export function createSingleArgumentStateOperator( - mutator: (state: EntityState) => void +export function createSingleArgumentStateOperator( + mutator: (state: EntityState) => void ) { - const operator = createStateOperator((_: undefined, state: EntityState) => - mutator(state) + const operator = createStateOperator( + (_: undefined, state: EntityState) => mutator(state) ) - return function operation>( - state: PreventAny + return function operation>( + state: PreventAny ): S { return operator(state as S, undefined) } } -export function createStateOperator( - mutator: (arg: R, state: EntityState) => void +export function createStateOperator( + mutator: (arg: R, state: EntityState) => void ) { - return function operation>( + return function operation>( state: S, arg: R | PayloadAction ): S { @@ -31,7 +31,7 @@ export function createStateOperator( return isFSA(arg) } - const runMutator = (draft: EntityState) => { + const runMutator = (draft: EntityState) => { if (isPayloadActionArgument(arg)) { mutator(arg.payload, draft) } else { diff --git a/packages/toolkit/src/entities/state_selectors.ts b/packages/toolkit/src/entities/state_selectors.ts index 46f59d3d9e..76a3a42dcd 100644 --- a/packages/toolkit/src/entities/state_selectors.ts +++ b/packages/toolkit/src/entities/state_selectors.ts @@ -7,17 +7,17 @@ import type { EntityId, } from './models' -export function createSelectorsFactory() { - function getSelectors(): EntitySelectors> +export function createSelectorsFactory() { + function getSelectors(): EntitySelectors, Id> function getSelectors( - selectState: (state: V) => EntityState - ): EntitySelectors + selectState: (state: V) => EntityState + ): EntitySelectors function getSelectors( - selectState?: (state: V) => EntityState - ): EntitySelectors { - const selectIds = (state: EntityState) => state.ids + selectState?: (state: V) => EntityState + ): EntitySelectors { + const selectIds = (state: EntityState) => state.ids - const selectEntities = (state: EntityState) => state.entities + const selectEntities = (state: EntityState) => state.entities const selectAll = createDraftSafeSelector( selectIds, @@ -25,9 +25,10 @@ export function createSelectorsFactory() { (ids, entities): T[] => ids.map((id) => entities[id]!) ) - const selectId = (_: unknown, id: EntityId) => id + const selectId = (_: unknown, id: Id) => id - const selectById = (entities: Dictionary, id: EntityId) => entities[id] + const selectById = (entities: Dictionary, id: Id) => + entities[id] as T | undefined const selectTotal = createDraftSafeSelector(selectIds, (ids) => ids.length) @@ -46,9 +47,9 @@ export function createSelectorsFactory() { } const selectGlobalizedEntities = createDraftSafeSelector( - selectState as Selector>, + selectState as Selector>, selectEntities - ) + ) as (state: any) => Partial> return { selectIds: createDraftSafeSelector(selectState, selectIds), diff --git a/packages/toolkit/src/entities/tests/entity_state.test.ts b/packages/toolkit/src/entities/tests/entity_state.test.ts index 773c96b89b..65accf475c 100644 --- a/packages/toolkit/src/entities/tests/entity_state.test.ts +++ b/packages/toolkit/src/entities/tests/entity_state.test.ts @@ -6,7 +6,7 @@ import { createSlice } from '../../createSlice' import type { BookModel } from './fixtures/book' describe('Entity State', () => { - let adapter: EntityAdapter + let adapter: EntityAdapter beforeEach(() => { adapter = createEntityAdapter({ diff --git a/packages/toolkit/src/entities/tests/state_adapter.test.ts b/packages/toolkit/src/entities/tests/state_adapter.test.ts index ed515fed6e..a05b715ff9 100644 --- a/packages/toolkit/src/entities/tests/state_adapter.test.ts +++ b/packages/toolkit/src/entities/tests/state_adapter.test.ts @@ -6,7 +6,7 @@ import { createSlice } from '../../createSlice' import type { BookModel } from './fixtures/book' describe('createStateOperator', () => { - let adapter: EntityAdapter + let adapter: EntityAdapter beforeEach(() => { adapter = createEntityAdapter({ diff --git a/packages/toolkit/src/entities/tests/state_selectors.test.ts b/packages/toolkit/src/entities/tests/state_selectors.test.ts index 9458c9c93a..b368e30b84 100644 --- a/packages/toolkit/src/entities/tests/state_selectors.test.ts +++ b/packages/toolkit/src/entities/tests/state_selectors.test.ts @@ -9,11 +9,11 @@ import { createSelector } from 'reselect' describe('Entity State Selectors', () => { describe('Composed Selectors', () => { interface State { - books: EntityState + books: EntityState } - let adapter: EntityAdapter - let selectors: EntitySelectors + let adapter: EntityAdapter + let selectors: EntitySelectors let state: State beforeEach(() => { @@ -65,10 +65,14 @@ describe('Entity State Selectors', () => { }) describe('Uncomposed Selectors', () => { - type State = EntityState - - let adapter: EntityAdapter - let selectors: EntitySelectors> + type State = EntityState + + let adapter: EntityAdapter + let selectors: EntitySelectors< + BookModel, + EntityState, + string + > let state: State beforeEach(() => { @@ -98,9 +102,9 @@ describe('Entity State Selectors', () => { }) it('should type single entity from Dictionary as entity type or undefined', () => { - expectType, BookModel | undefined>>( - createSelector(selectors.selectEntities, (entities) => entities[0]) - ) + expectType< + Selector, BookModel | undefined> + >(createSelector(selectors.selectEntities, (entities) => entities[0])) }) it('should create a selector for selecting the list of models', () => { diff --git a/packages/toolkit/src/entities/unsorted_state_adapter.ts b/packages/toolkit/src/entities/unsorted_state_adapter.ts index ffa104a74e..55ae8d3e2e 100644 --- a/packages/toolkit/src/entities/unsorted_state_adapter.ts +++ b/packages/toolkit/src/entities/unsorted_state_adapter.ts @@ -15,10 +15,10 @@ import { splitAddedUpdatedEntities, } from './utils' -export function createUnsortedStateAdapter( - selectId: IdSelector -): EntityStateAdapter { - type R = EntityState +export function createUnsortedStateAdapter( + selectId: IdSelector +): EntityStateAdapter { + type R = EntityState function addOneMutably(entity: T, state: R): void { const key = selectIdValue(entity, selectId) @@ -32,7 +32,7 @@ export function createUnsortedStateAdapter( } function addManyMutably( - newEntities: readonly T[] | Record, + newEntities: readonly T[] | Record, state: R ): void { newEntities = ensureEntitiesArray(newEntities) @@ -51,7 +51,7 @@ export function createUnsortedStateAdapter( } function setManyMutably( - newEntities: readonly T[] | Record, + newEntities: readonly T[] | Record, state: R ): void { newEntities = ensureEntitiesArray(newEntities) @@ -61,7 +61,7 @@ export function createUnsortedStateAdapter( } function setAllMutably( - newEntities: readonly T[] | Record, + newEntities: readonly T[] | Record, state: R ): void { newEntities = ensureEntitiesArray(newEntities) @@ -72,11 +72,11 @@ export function createUnsortedStateAdapter( addManyMutably(newEntities, state) } - function removeOneMutably(key: EntityId, state: R): void { + function removeOneMutably(key: Id, state: R): void { return removeManyMutably([key], state) } - function removeManyMutably(keys: readonly EntityId[], state: R): void { + function removeManyMutably(keys: readonly Id[], state: R): void { let didMutate = false keys.forEach((key) => { @@ -99,11 +99,11 @@ export function createUnsortedStateAdapter( } function takeNewKey( - keys: { [id: string]: EntityId }, - update: Update, + keys: { [id: string]: Id }, + update: Update, state: R ): boolean { - const original = state.entities[update.id] + const original: T | undefined = state.entities[update.id] const updated: T = Object.assign({}, original, update.changes) const newKey = selectIdValue(updated, selectId) const hasNewKey = newKey !== update.id @@ -118,17 +118,17 @@ export function createUnsortedStateAdapter( return hasNewKey } - function updateOneMutably(update: Update, state: R): void { + function updateOneMutably(update: Update, state: R): void { return updateManyMutably([update], state) } function updateManyMutably( - updates: ReadonlyArray>, + updates: ReadonlyArray>, state: R ): void { - const newKeys: { [id: string]: EntityId } = {} + const newKeys: { [id: string]: Id } = {} - const updatesPerEntity: { [id: string]: Update } = {} + const updatesPerEntity: { [id: string]: Update } = {} updates.forEach((update) => { // Only apply updates to entities that currently exist @@ -168,10 +168,10 @@ export function createUnsortedStateAdapter( } function upsertManyMutably( - newEntities: readonly T[] | Record, + newEntities: readonly T[] | Record, state: R ): void { - const [added, updated] = splitAddedUpdatedEntities( + const [added, updated] = splitAddedUpdatedEntities( newEntities, selectId, state diff --git a/packages/toolkit/src/entities/utils.ts b/packages/toolkit/src/entities/utils.ts index 5a4be0fca5..8c86f6184c 100644 --- a/packages/toolkit/src/entities/utils.ts +++ b/packages/toolkit/src/entities/utils.ts @@ -1,6 +1,9 @@ import type { EntityState, IdSelector, Update, EntityId } from './models' -export function selectIdValue(entity: T, selectId: IdSelector) { +export function selectIdValue( + entity: T, + selectId: IdSelector +) { const key = selectId(entity) if (process.env.NODE_ENV !== 'production' && key === undefined) { @@ -17,8 +20,8 @@ export function selectIdValue(entity: T, selectId: IdSelector) { return key } -export function ensureEntitiesArray( - entities: readonly T[] | Record +export function ensureEntitiesArray( + entities: readonly T[] | Record ): readonly T[] { if (!Array.isArray(entities)) { entities = Object.values(entities) @@ -27,15 +30,15 @@ export function ensureEntitiesArray( return entities } -export function splitAddedUpdatedEntities( - newEntities: readonly T[] | Record, - selectId: IdSelector, - state: EntityState -): [T[], Update[]] { +export function splitAddedUpdatedEntities( + newEntities: readonly T[] | Record, + selectId: IdSelector, + state: EntityState +): [T[], Update[]] { newEntities = ensureEntitiesArray(newEntities) const added: T[] = [] - const updated: Update[] = [] + const updated: Update[] = [] for (const entity of newEntities) { const id = selectIdValue(entity, selectId) diff --git a/packages/toolkit/src/tests/combinedTest.test.ts b/packages/toolkit/src/tests/combinedTest.test.ts index fada468601..7f906d8182 100644 --- a/packages/toolkit/src/tests/combinedTest.test.ts +++ b/packages/toolkit/src/tests/combinedTest.test.ts @@ -10,7 +10,7 @@ import type { EntityAdapter } from '@internal/entities/models' import type { BookModel } from '@internal/entities/tests/fixtures/book' describe('Combined entity slice', () => { - let adapter: EntityAdapter + let adapter: EntityAdapter beforeEach(() => { adapter = createEntityAdapter({ diff --git a/packages/toolkit/src/tests/createEntityAdapter.typetest.ts b/packages/toolkit/src/tests/createEntityAdapter.typetest.ts index 10c2b4a393..12bf4295a7 100644 --- a/packages/toolkit/src/tests/createEntityAdapter.typetest.ts +++ b/packages/toolkit/src/tests/createEntityAdapter.typetest.ts @@ -9,9 +9,9 @@ import type { import { createSlice, createEntityAdapter } from '@reduxjs/toolkit' import { expectType } from './helpers' -function extractReducers( - adapter: EntityAdapter -): Omit, 'map'> { +function extractReducers( + adapter: EntityAdapter +): Omit, 'map'> { const { selectId, sortComparer, getInitialState, getSelectors, ...rest } = adapter return rest @@ -21,7 +21,9 @@ function extractReducers( * should be usable in a slice, with all the "reducer-like" functions */ { + type Id = EntityId & { readonly __tag: unique symbol } type Entity = { + id: Id value: string } const adapter = createEntityAdapter() @@ -35,7 +37,7 @@ function extractReducers( expectType>(slice.actions.addOne) expectType< - ActionCreatorWithPayload | Record> + ActionCreatorWithPayload | Record> >(slice.actions.addMany) expectType< ActionCreatorWithPayload | Record> @@ -48,26 +50,28 @@ function extractReducers( // @ts-expect-error slice.actions.setAll ) - expectType>(slice.actions.removeOne) - expectType>>( + expectType>(slice.actions.removeOne) + expectType>>( slice.actions.removeMany ) // @ts-expect-error - expectType>(slice.actions.removeMany) + expectType>(slice.actions.removeMany) expectType(slice.actions.removeAll) - expectType>>(slice.actions.updateOne) - expectType[]>>( + expectType>>( + slice.actions.updateOne + ) + expectType[]>>( // @ts-expect-error slice.actions.updateMany ) - expectType>>>( + expectType>>>( slice.actions.updateMany ) expectType>(slice.actions.upsertOne) expectType< - ActionCreatorWithPayload | Record> + ActionCreatorWithPayload | Record> >(slice.actions.upsertMany) - expectType>>( + expectType>>( // @ts-expect-error slice.actions.upsertMany ) @@ -78,9 +82,11 @@ function extractReducers( */ { type Entity = { + id: EntityId value: string } type Entity2 = { + id: EntityId value2: string } const adapter = createEntityAdapter() @@ -101,6 +107,7 @@ function extractReducers( */ { type Entity = { + id: EntityId value: string } const adapter = createEntityAdapter() @@ -118,6 +125,7 @@ function extractReducers( */ { type Entity = { + id: EntityId value: string } const adapter = createEntityAdapter() From 783913368a1db1aeb74d6130e323eac33f7de34e Mon Sep 17 00:00:00 2001 From: Matt Date: Sat, 5 Mar 2022 13:27:15 +0000 Subject: [PATCH 2/4] Improve types of createEntityAdapter --- .../toolkit/src/entities/create_adapter.ts | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/packages/toolkit/src/entities/create_adapter.ts b/packages/toolkit/src/entities/create_adapter.ts index 39d97ede4f..15ec788719 100644 --- a/packages/toolkit/src/entities/create_adapter.ts +++ b/packages/toolkit/src/entities/create_adapter.ts @@ -10,18 +10,21 @@ import { createSelectorsFactory } from './state_selectors' import { createSortedStateAdapter } from './sorted_state_adapter' import { createUnsortedStateAdapter } from './unsorted_state_adapter' -type ExtractEntityId = T extends { id: infer Id } - ? Id - : never - -export function createEntityAdapter(options?: { +export interface EntityAdapterOptions { + selectId?: IdSelector sortComparer?: false | Comparer -}): EntityAdapter> +} -export function createEntityAdapter(options: { - selectId: IdSelector - sortComparer?: false | Comparer -}): EntityAdapter +type IsEntityId = T extends EntityId ? T : EntityId + +type ExtractId = T extends { id: infer Id } ? Id : never + +type ExtractEntityId< + T, + O extends EntityAdapterOptions +> = O['selectId'] extends IdSelector + ? Id + : IsEntityId> /** * @@ -29,12 +32,11 @@ export function createEntityAdapter(options: { * * @public */ -export function createEntityAdapter( - options: { - selectId?: IdSelector - sortComparer?: false | Comparer - } = {} -): EntityAdapter { +export function createEntityAdapter< + T, + O extends EntityAdapterOptions = EntityAdapterOptions +>(options: O = {} as O): EntityAdapter> { + type Id = ExtractEntityId const { selectId, sortComparer }: EntityDefinition = { sortComparer: false, selectId: (instance: any) => instance.id as Id, From 155e64ecbc9fafc34d4244bb4d7ea138aa8d93da Mon Sep 17 00:00:00 2001 From: Matt Date: Sat, 2 Apr 2022 08:59:38 +0100 Subject: [PATCH 3/4] Fix DictionaryNum definition --- packages/toolkit/src/entities/models.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/toolkit/src/entities/models.ts b/packages/toolkit/src/entities/models.ts index b6180bea70..370e750baf 100644 --- a/packages/toolkit/src/entities/models.ts +++ b/packages/toolkit/src/entities/models.ts @@ -24,7 +24,7 @@ export type Dictionary = Partial> /** * @public */ -export type DictionaryNum = Dictionary +export type DictionaryNum = Dictionary /** * @public From 0e796262c93fdc6b0317a4081963776c3dddada1 Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 4 Apr 2022 18:48:54 +0100 Subject: [PATCH 4/4] Update documentation, remove DictionaryNum --- docs/rtk-query/usage/streaming-updates.mdx | 2 +- .../src/components/Counter/Counter.tsx | 2 +- packages/toolkit/etc/redux-toolkit.api.md | 1085 +++++++---------- packages/toolkit/src/entities/models.ts | 4 - 4 files changed, 457 insertions(+), 636 deletions(-) diff --git a/docs/rtk-query/usage/streaming-updates.mdx b/docs/rtk-query/usage/streaming-updates.mdx index 2635a94e72..ec3550b5bd 100644 --- a/docs/rtk-query/usage/streaming-updates.mdx +++ b/docs/rtk-query/usage/streaming-updates.mdx @@ -157,7 +157,7 @@ export const api = createApi({ baseQuery: fetchBaseQuery({ baseUrl: '/' }), endpoints: (build) => ({ // highlight-start - getMessages: build.query, Channel>({ + getMessages: build.query, Channel>({ // highlight-end query: (channel) => `messages/${channel}`, // highlight-start diff --git a/examples/action-listener/counter/src/components/Counter/Counter.tsx b/examples/action-listener/counter/src/components/Counter/Counter.tsx index 831c3d130d..bac44f3ebb 100644 --- a/examples/action-listener/counter/src/components/Counter/Counter.tsx +++ b/examples/action-listener/counter/src/components/Counter/Counter.tsx @@ -6,7 +6,7 @@ import styles from './counter.module.css' import clsx from 'clsx' export interface CounterProps { - counterId: EntityId + counterId: string } const intervalMs = 1_000 diff --git a/packages/toolkit/etc/redux-toolkit.api.md b/packages/toolkit/etc/redux-toolkit.api.md index 62dd27159c..639461cb4a 100644 --- a/packages/toolkit/etc/redux-toolkit.api.md +++ b/packages/toolkit/etc/redux-toolkit.api.md @@ -3,685 +3,497 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import type { Action } from 'redux' -import type { ActionCreator } from 'redux' -import type { AnyAction } from 'redux' -import type { CombinedState } from 'redux' -import { default as createNextState } from 'immer' -import { createSelector } from 'reselect' -import { current } from 'immer' -import type { Dispatch } from 'redux' -import { Draft } from 'immer' -import { freeze } from 'immer' -import { isDraft } from 'immer' -import type { Middleware } from 'redux' -import { original } from 'immer' -import { OutputParametricSelector } from 'reselect' -import { OutputSelector } from 'reselect' -import { ParametricSelector } from 'reselect' -import type { PreloadedState } from 'redux' -import type { Reducer } from 'redux' -import type { ReducersMapObject } from 'redux' -import { Selector } from 'reselect' -import type { Store } from 'redux' -import type { StoreEnhancer } from 'redux' -import { ThunkAction } from 'redux-thunk' -import { ThunkDispatch } from 'redux-thunk' -import type { ThunkMiddleware } from 'redux-thunk' - -// @public -export interface ActionCreatorWithNonInferrablePayload< - T extends string = string -> extends BaseActionCreator { - (payload: PT): PayloadAction + +import type { Action } from 'redux'; +import type { ActionCreator } from 'redux'; +import type { AnyAction } from 'redux'; +import type { CombinedState } from 'redux'; +import { default as createNextState } from 'immer'; +import { createSelector } from 'reselect'; +import { current } from 'immer'; +import type { Dispatch } from 'redux'; +import { Draft } from 'immer'; +import { freeze } from 'immer'; +import { isDraft } from 'immer'; +import type { Middleware } from 'redux'; +import type { MiddlewareAPI } from 'redux'; +import { original } from 'immer'; +import { OutputParametricSelector } from 'reselect'; +import { OutputSelector } from 'reselect'; +import { ParametricSelector } from 'reselect'; +import type { PreloadedState } from 'redux'; +import type { Reducer } from 'redux'; +import type { ReducersMapObject } from 'redux'; +import { Selector } from 'reselect'; +import type { SerializedError as SerializedError_2 } from '@reduxjs/toolkit'; +import type { Store } from 'redux'; +import type { StoreEnhancer } from 'redux'; +import { ThunkAction } from 'redux-thunk'; +import { ThunkDispatch } from 'redux-thunk'; +import type { ThunkMiddleware } from 'redux-thunk'; + +// @public +export interface ActionCreatorWithNonInferrablePayload extends BaseActionCreator { + (payload: PT): PayloadAction; } // @public -export interface ActionCreatorWithOptionalPayload - extends BaseActionCreator { - (payload?: P): PayloadAction +export interface ActionCreatorWithOptionalPayload extends BaseActionCreator { + (payload?: P): PayloadAction; } // @public -export interface ActionCreatorWithoutPayload - extends BaseActionCreator { - (): PayloadAction +export interface ActionCreatorWithoutPayload extends BaseActionCreator { + (): PayloadAction; } // @public -export interface ActionCreatorWithPayload - extends BaseActionCreator { - (payload: P): PayloadAction +export interface ActionCreatorWithPayload extends BaseActionCreator { + (payload: P): PayloadAction; } // @public -export interface ActionCreatorWithPreparedPayload< - Args extends unknown[], - P, - T extends string = string, - E = never, - M = never -> extends BaseActionCreator { - (...args: Args): PayloadAction +export interface ActionCreatorWithPreparedPayload extends BaseActionCreator { + (...args: Args): PayloadAction; } // @public (undocumented) -export type ActionMatchingAllOf< - Matchers extends [Matcher, ...Matcher[]] -> = UnionToIntersection> +export type ActionMatchingAllOf, ...Matcher[]]> = UnionToIntersection>; // @public (undocumented) -export type ActionMatchingAnyOf< - Matchers extends [Matcher, ...Matcher[]] -> = ActionFromMatcher +export type ActionMatchingAnyOf, ...Matcher[]]> = ActionFromMatcher; // @public export interface ActionReducerMapBuilder { - addCase>( - actionCreator: ActionCreator, - reducer: CaseReducer> - ): ActionReducerMapBuilder - addCase>( - type: Type, - reducer: CaseReducer - ): ActionReducerMapBuilder - addDefaultCase(reducer: CaseReducer): {} - addMatcher( - matcher: TypeGuard | ((action: any) => boolean), - reducer: CaseReducer - ): Omit, 'addCase'> + addCase>(actionCreator: ActionCreator, reducer: CaseReducer>): ActionReducerMapBuilder; + addCase>(type: Type, reducer: CaseReducer): ActionReducerMapBuilder; + addDefaultCase(reducer: CaseReducer): {}; + addMatcher(matcher: TypeGuard | ((action: any) => boolean), reducer: CaseReducer): Omit, 'addCase'>; } // @public @deprecated -export type Actions = Record - -// @public -export type AsyncThunk< - Returned, - ThunkArg, - ThunkApiConfig extends AsyncThunkConfig -> = AsyncThunkActionCreator & { - pending: AsyncThunkPendingActionCreator - rejected: AsyncThunkRejectedActionCreator - fulfilled: AsyncThunkFulfilledActionCreator< - Returned, - ThunkArg, - ThunkApiConfig - > - typePrefix: string +export type Actions = Record; + +// @public (undocumented) +export const addListener: TypedAddListener, unknown, ListenerEntry>, "listenerMiddleware/add">; + +// @public (undocumented) +export interface AsyncTaskExecutor { + // (undocumented) + (forkApi: ForkedTaskAPI): Promise; } // @public -export type AsyncThunkAction< - Returned, - ThunkArg, - ThunkApiConfig extends AsyncThunkConfig -> = ( - dispatch: GetDispatch, - getState: () => GetState, - extra: GetExtra -) => Promise< - | ReturnType> - | ReturnType> -> & { - abort: (reason?: string) => void - requestId: string - arg: ThunkArg - unwrap: () => Promise -} +export type AsyncThunk = AsyncThunkActionCreator & { + pending: AsyncThunkPendingActionCreator; + rejected: AsyncThunkRejectedActionCreator; + fulfilled: AsyncThunkFulfilledActionCreator; + typePrefix: string; +}; + +// @public +export type AsyncThunkAction = (dispatch: GetDispatch, getState: () => GetState, extra: GetExtra) => Promise> | ReturnType>> & { + abort: (reason?: string) => void; + requestId: string; + arg: ThunkArg; + unwrap: () => Promise; +}; + +// @public +export type AsyncThunkOptions = { + condition?(arg: ThunkArg, api: Pick, 'getState' | 'extra'>): MaybePromise; + dispatchConditionRejection?: boolean; + serializeError?: (x: unknown) => GetSerializedErrorType; + idGenerator?: (arg: ThunkArg) => string; +} & IsUnknown, { + getPendingMeta?(base: { + arg: ThunkArg; + requestId: string; + }, api: Pick, 'getState' | 'extra'>): GetPendingMeta; +}, { + getPendingMeta(base: { + arg: ThunkArg; + requestId: string; + }, api: Pick, 'getState' | 'extra'>): GetPendingMeta; +}>; // @public -export type AsyncThunkOptions< - ThunkArg = void, - ThunkApiConfig extends AsyncThunkConfig = {} -> = { - condition?( - arg: ThunkArg, - api: Pick, 'getState' | 'extra'> - ): MaybePromise - dispatchConditionRejection?: boolean - serializeError?: (x: unknown) => GetSerializedErrorType - idGenerator?: (arg: ThunkArg) => string -} & IsUnknown< - GetPendingMeta, - { - getPendingMeta?( - base: { - arg: ThunkArg - requestId: string - }, - api: Pick, 'getState' | 'extra'> - ): GetPendingMeta - }, - { - getPendingMeta( - base: { - arg: ThunkArg - requestId: string - }, - api: Pick, 'getState' | 'extra'> - ): GetPendingMeta - } -> - -// @public -export type AsyncThunkPayloadCreator< - Returned, - ThunkArg = void, - ThunkApiConfig extends AsyncThunkConfig = {} -> = ( - arg: ThunkArg, - thunkAPI: GetThunkAPI -) => AsyncThunkPayloadCreatorReturnValue - -// @public -export type AsyncThunkPayloadCreatorReturnValue< - Returned, - ThunkApiConfig extends AsyncThunkConfig -> = MaybePromise< - | IsUnknown< - GetFulfilledMeta, - Returned, - FulfillWithMeta> - > - | RejectWithValue< - GetRejectValue, - GetRejectedMeta - > -> - -// @public -export type CaseReducer = ( - state: Draft, - action: A -) => S | void | Draft +export type AsyncThunkPayloadCreator = (arg: ThunkArg, thunkAPI: GetThunkAPI) => AsyncThunkPayloadCreatorReturnValue; + +// @public +export type AsyncThunkPayloadCreatorReturnValue = MaybePromise, Returned, FulfillWithMeta>> | RejectWithValue, GetRejectedMeta>>; + +// @public +export type CaseReducer = (state: Draft, action: A) => S | void | Draft; // @public export type CaseReducerActions> = { - [Type in keyof CaseReducers]: CaseReducers[Type] extends { - prepare: any - } - ? ActionCreatorForCaseReducerWithPrepare - : ActionCreatorForCaseReducer -} + [Type in keyof CaseReducers]: CaseReducers[Type] extends { + prepare: any; + } ? ActionCreatorForCaseReducerWithPrepare : ActionCreatorForCaseReducer; +}; // @public @deprecated export type CaseReducers = { - [T in keyof AS]: AS[T] extends Action ? CaseReducer : void -} + [T in keyof AS]: AS[T] extends Action ? CaseReducer : void; +}; // @public export type CaseReducerWithPrepare = { - reducer: CaseReducer - prepare: PrepareAction -} + reducer: CaseReducer; + prepare: PrepareAction; +}; // @public (undocumented) -export type Comparer = (a: T, b: T) => number +export const clearAllListeners: ActionCreatorWithoutPayload; + +// @public (undocumented) +export type Comparer = (a: T, b: T) => number; // @public -export type ConfigureEnhancersCallback = ( - defaultEnhancers: readonly StoreEnhancer[] -) => StoreEnhancer[] +export type ConfigureEnhancersCallback = (defaultEnhancers: readonly StoreEnhancer[]) => StoreEnhancer[]; // @public -export function configureStore< - S = any, - A extends Action = AnyAction, - M extends Middlewares = [ThunkMiddlewareFor] ->(options: ConfigureStoreOptions): EnhancedStore +export function configureStore = [ThunkMiddlewareFor]>(options: ConfigureStoreOptions): EnhancedStore; // @public -export interface ConfigureStoreOptions< - S = any, - A extends Action = AnyAction, - M extends Middlewares = Middlewares -> { - devTools?: boolean | EnhancerOptions - enhancers?: StoreEnhancer[] | ConfigureEnhancersCallback - middleware?: ((getDefaultMiddleware: CurriedGetDefaultMiddleware) => M) | M - preloadedState?: PreloadedState>> - reducer: Reducer | ReducersMapObject +export interface ConfigureStoreOptions = Middlewares> { + devTools?: boolean | EnhancerOptions; + enhancers?: StoreEnhancer[] | ConfigureEnhancersCallback; + middleware?: ((getDefaultMiddleware: CurriedGetDefaultMiddleware) => M) | M; + preloadedState?: PreloadedState>>; + reducer: Reducer | ReducersMapObject; } // @public -export function createAction

( - type: T -): PayloadActionCreator +export function createAction

| void = void -> = IfPrepareActionMethodProvided< - PA, - _ActionCreatorWithPreparedPayload, - IsAny< - P, - ActionCreatorWithPayload, - IsUnknownOrNonInferrable< - P, - ActionCreatorWithNonInferrablePayload, - IfVoid< - P, - ActionCreatorWithoutPayload, - IfMaybeUndefined< - P, - ActionCreatorWithOptionalPayload, - ActionCreatorWithPayload - > - > - > - > -> - -// @public -export type PrepareAction

= - | ((...args: any[]) => { - payload: P - }) - | ((...args: any[]) => { - payload: P - meta: any - }) - | ((...args: any[]) => { - payload: P - error: any - }) - | ((...args: any[]) => { - payload: P - meta: any - error: any - }) +export type PayloadAction

= { + payload: P; + type: T; +} & ([M] extends [never] ? {} : { + meta: M; +}) & ([E] extends [never] ? {} : { + error: E; +}); + +// @public +export type PayloadActionCreator

| void = void> = IfPrepareActionMethodProvided, IsAny, IsUnknownOrNonInferrable, IfVoid, IfMaybeUndefined, ActionCreatorWithPayload>>>>>; + +// @public +export type PrepareAction

= ((...args: any[]) => { + payload: P; +}) | ((...args: any[]) => { + payload: P; + meta: any; +}) | ((...args: any[]) => { + payload: P; + error: any; +}) | ((...args: any[]) => { + payload: P; + meta: any; + error: any; +}); + +// @public (undocumented) +export const removeListener: TypedRemoveListener, ListenerEntry>, "listenerMiddleware/remove">; export { Selector } // @public export interface SerializableStateInvariantMiddlewareOptions { - getEntries?: (value: any) => [string, any][] - ignoredActionPaths?: string[] - ignoredActions?: string[] - ignoredPaths?: string[] - ignoreState?: boolean - isSerializable?: (value: any) => boolean - warnAfter?: number + getEntries?: (value: any) => [string, any][]; + ignoreActions?: boolean; + ignoredActionPaths?: string[]; + ignoredActions?: string[]; + ignoredPaths?: string[]; + ignoreState?: boolean; + isSerializable?: (value: any) => boolean; + warnAfter?: number; } // @public (undocumented) export interface SerializedError { - // (undocumented) - code?: string - // (undocumented) - message?: string - // (undocumented) - name?: string - // (undocumented) - stack?: string + // (undocumented) + code?: string; + // (undocumented) + message?: string; + // (undocumented) + name?: string; + // (undocumented) + stack?: string; } // @public -export interface Slice< - State = any, - CaseReducers extends SliceCaseReducers = SliceCaseReducers, - Name extends string = string -> { - actions: CaseReducerActions - caseReducers: SliceDefinedCaseReducers - getInitialState: () => State - name: Name - reducer: Reducer +export interface Slice = SliceCaseReducers, Name extends string = string> { + actions: CaseReducerActions; + caseReducers: SliceDefinedCaseReducers; + getInitialState: () => State; + name: Name; + reducer: Reducer; } // @public @deprecated -export type SliceActionCreator

= PayloadActionCreator

+export type SliceActionCreator

= PayloadActionCreator

; // @public export type SliceCaseReducers = { - [K: string]: - | CaseReducer> - | CaseReducerWithPrepare> + [K: string]: CaseReducer> | CaseReducerWithPrepare>; +}; + +// @public (undocumented) +export interface SyncTaskExecutor { + // (undocumented) + (forkApi: ForkedTaskAPI): T; +} + +// @public (undocumented) +export class TaskAbortError implements SerializedError_2 { + constructor(code: string | undefined); + // (undocumented) + code: string | undefined; + // (undocumented) + message: string; + // (undocumented) + name: string; } +// @public (undocumented) +export type TaskCancelled = { + readonly status: 'cancelled'; + readonly error: TaskAbortError; +}; + +// @public (undocumented) +export type TaskRejected = { + readonly status: 'rejected'; + readonly error: unknown; +}; + +// @public (undocumented) +export type TaskResolved = { + readonly status: 'ok'; + readonly value: T; +}; + +// @public (undocumented) +export type TaskResult = TaskResolved | TaskRejected | TaskCancelled; + export { ThunkAction } export { ThunkDispatch } +// @public +export type TypedAddListener = ThunkDispatch, ExtraArgument = unknown, Payload = ListenerEntry, T extends string = 'listenerMiddleware/add'> = BaseActionCreator & AddListenerOverloads, State, Dispatch, ExtraArgument>; + +// @public +export type TypedRemoveListener = ThunkDispatch, Payload = ListenerEntry, T extends string = 'listenerMiddleware/remove'> = BaseActionCreator & AddListenerOverloads, State, Dispatch, any, UnsubscribeListenerOptions>; + +// @public +export type TypedStartListening = ThunkDispatch, ExtraArgument = unknown> = AddListenerOverloads; + +// @public +export type TypedStopListening = ThunkDispatch> = RemoveListenerOverloads; + // @public (undocumented) -export function unwrapResult( - action: R -): UnwrappedActionPayload +export type UnsubscribeListener = (unsuscribeOptions?: UnsubscribeListenerOptions) => void; // @public (undocumented) -export type Update = { - id: EntityId - changes: Partial +export interface UnsubscribeListenerOptions { + // (undocumented) + cancelActive?: true; } +// @public (undocumented) +export function unwrapResult(action: R): UnwrappedActionPayload; + +// @public (undocumented) +export type Update = { + id: Id; + changes: Partial; +}; + // @public -export type ValidateSliceCaseReducers< - S, - ACR extends SliceCaseReducers -> = ACR & - { +export type ValidateSliceCaseReducers> = ACR & { [T in keyof ACR]: ACR[T] extends { - reducer(s: S, action?: infer A): any - } - ? { - prepare(...a: never[]): Omit - } - : {} - } + reducer(s: S, action?: infer A): any; + } ? { + prepare(...a: never[]): Omit; + } : {}; +}; -export * from 'redux' + +export * from "redux"; // (No @packageDocumentation comment for this package) + ``` diff --git a/packages/toolkit/src/entities/models.ts b/packages/toolkit/src/entities/models.ts index 370e750baf..2a6cc6b244 100644 --- a/packages/toolkit/src/entities/models.ts +++ b/packages/toolkit/src/entities/models.ts @@ -21,10 +21,6 @@ export type IdSelector = (model: T) => Id */ export type Dictionary = Partial> -/** - * @public - */ -export type DictionaryNum = Dictionary /** * @public

(type: T): PayloadActionCreator; // @public -export function createAction< - PA extends PrepareAction, - T extends string = string ->( - type: T, - prepareAction: PA -): PayloadActionCreator['payload'], T, PA> +export function createAction, T extends string = string>(type: T, prepareAction: PA): PayloadActionCreator['payload'], T, PA>; // @public (undocumented) -export function createAsyncThunk( - typePrefix: string, - payloadCreator: AsyncThunkPayloadCreator, - options?: AsyncThunkOptions -): AsyncThunk +export function createAsyncThunk(typePrefix: string, payloadCreator: AsyncThunkPayloadCreator, options?: AsyncThunkOptions): AsyncThunk; // @public (undocumented) -export function createAsyncThunk< - Returned, - ThunkArg, - ThunkApiConfig extends AsyncThunkConfig ->( - typePrefix: string, - payloadCreator: AsyncThunkPayloadCreator, - options?: AsyncThunkOptions -): AsyncThunk +export function createAsyncThunk(typePrefix: string, payloadCreator: AsyncThunkPayloadCreator, options?: AsyncThunkOptions): AsyncThunk; // @public -export const createDraftSafeSelector: typeof createSelector +export const createDraftSafeSelector: typeof createSelector; // @public (undocumented) -export function createEntityAdapter(options?: { - selectId?: IdSelector - sortComparer?: false | Comparer -}): EntityAdapter +export function createEntityAdapter = EntityAdapterOptions>(options?: O): EntityAdapter>; // @public -export function createImmutableStateInvariantMiddleware( - options?: ImmutableStateInvariantMiddlewareOptions -): Middleware +export function createImmutableStateInvariantMiddleware(options?: ImmutableStateInvariantMiddlewareOptions): Middleware; + +// @public (undocumented) +export function createListenerMiddleware = ThunkDispatch, ExtraArgument = unknown>(middlewareOptions?: CreateListenerMiddlewareOptions): ListenerMiddlewareInstance; + +// @public (undocumented) +export interface CreateListenerMiddlewareOptions { + // (undocumented) + extra?: ExtraArgument; + onError?: ListenerErrorHandler; +} export { createNextState } // @public -export function createReducer>( - initialState: S | (() => S), - builderCallback: (builder: ActionReducerMapBuilder) => void -): ReducerWithInitialState +export function createReducer>(initialState: S | (() => S), builderCallback: (builder: ActionReducerMapBuilder) => void): ReducerWithInitialState; // @public -export function createReducer< - S extends NotFunction, - CR extends CaseReducers = CaseReducers ->( - initialState: S | (() => S), - actionsMap: CR, - actionMatchers?: ActionMatcherDescriptionCollection, - defaultCaseReducer?: CaseReducer -): ReducerWithInitialState +export function createReducer, CR extends CaseReducers = CaseReducers>(initialState: S | (() => S), actionsMap: CR, actionMatchers?: ActionMatcherDescriptionCollection, defaultCaseReducer?: CaseReducer): ReducerWithInitialState; export { createSelector } // @public -export function createSerializableStateInvariantMiddleware( - options?: SerializableStateInvariantMiddlewareOptions -): Middleware +export function createSerializableStateInvariantMiddleware(options?: SerializableStateInvariantMiddlewareOptions): Middleware; // @public -export function createSlice< - State, - CaseReducers extends SliceCaseReducers, - Name extends string = string ->( - options: CreateSliceOptions -): Slice +export function createSlice, Name extends string = string>(options: CreateSliceOptions): Slice; // @public -export interface CreateSliceOptions< - State = any, - CR extends SliceCaseReducers = SliceCaseReducers, - Name extends string = string -> { - extraReducers?: - | CaseReducers, any> - | ((builder: ActionReducerMapBuilder>) => void) - initialState: State | (() => State) - name: Name - reducers: ValidateSliceCaseReducers +export interface CreateSliceOptions = SliceCaseReducers, Name extends string = string> { + extraReducers?: CaseReducers, any> | ((builder: ActionReducerMapBuilder>) => void); + initialState: State | (() => State); + name: Name; + reducers: ValidateSliceCaseReducers; } export { current } // @public (undocumented) -export interface Dictionary extends DictionaryNum { - // (undocumented) - [id: string]: T | undefined -} +export type Dictionary = Partial>; export { Draft } // @public -export interface EnhancedStore< - S = any, - A extends Action = AnyAction, - M extends Middlewares = Middlewares -> extends Store { - dispatch: Dispatch & DispatchForMiddlewares +export interface EnhancedStore = Middlewares> extends Store { + dispatch: ExtractDispatchExtensions & Dispatch; } // @public (undocumented) -export interface EntityAdapter extends EntityStateAdapter { - // (undocumented) - getInitialState(): EntityState - // (undocumented) - getInitialState(state: S): EntityState & S - // (undocumented) - getSelectors(): EntitySelectors> - // (undocumented) - getSelectors( - selectState: (state: V) => EntityState - ): EntitySelectors - // (undocumented) - selectId: IdSelector - // (undocumented) - sortComparer: false | Comparer +export interface EntityAdapter extends EntityStateAdapter { + // (undocumented) + getInitialState(): EntityState; + // (undocumented) + getInitialState(state: S): EntityState & S; + // (undocumented) + getSelectors(): EntitySelectors, Id>; + // (undocumented) + getSelectors(selectState: (state: V) => EntityState): EntitySelectors; + // (undocumented) + selectId: IdSelector; + // (undocumented) + sortComparer: false | Comparer; +} + +// @public (undocumented) +export type EntityId = number | string; + +// @public (undocumented) +export interface EntitySelectors { + // (undocumented) + selectAll: (state: V) => T[]; + // (undocumented) + selectById: (state: V, id: Id) => T | undefined; + // (undocumented) + selectEntities: (state: V) => Dictionary; + // (undocumented) + selectIds: (state: V) => Id[]; + // (undocumented) + selectTotal: (state: V) => number; } // @public (undocumented) -export type EntityId = number | string +export interface EntityState { + // (undocumented) + entities: Dictionary; + // (undocumented) + ids: Id[]; +} // @public (undocumented) -export interface EntitySelectors { - // (undocumented) - selectAll: (state: V) => T[] - // (undocumented) - selectById: (state: V, id: EntityId) => T | undefined - // (undocumented) - selectEntities: (state: V) => Dictionary - // (undocumented) - selectIds: (state: V) => EntityId[] - // (undocumented) - selectTotal: (state: V) => number +export interface EntityStateAdapter { + // (undocumented) + addMany>(state: PreventAny, entities: readonly T[] | Record): S; + // (undocumented) + addMany>(state: PreventAny, entities: PayloadAction>): S; + // (undocumented) + addOne>(state: PreventAny, entity: T): S; + // (undocumented) + addOne>(state: PreventAny, action: PayloadAction): S; + // (undocumented) + removeAll>(state: PreventAny): S; + // (undocumented) + removeMany>(state: PreventAny, keys: readonly Id[]): S; + // (undocumented) + removeMany>(state: PreventAny, keys: PayloadAction): S; + // (undocumented) + removeOne>(state: PreventAny, key: Id): S; + // (undocumented) + removeOne>(state: PreventAny, key: PayloadAction): S; + // (undocumented) + setAll>(state: PreventAny, entities: readonly T[] | Record): S; + // (undocumented) + setAll>(state: PreventAny, entities: PayloadAction>): S; + // (undocumented) + setMany>(state: PreventAny, entities: readonly T[] | Record): S; + // (undocumented) + setMany>(state: PreventAny, entities: PayloadAction>): S; + // (undocumented) + setOne>(state: PreventAny, entity: T): S; + // (undocumented) + setOne>(state: PreventAny, action: PayloadAction): S; + // (undocumented) + updateMany>(state: PreventAny, updates: ReadonlyArray>): S; + // (undocumented) + updateMany>(state: PreventAny, updates: PayloadAction>>): S; + // (undocumented) + updateOne>(state: PreventAny, update: Update): S; + // (undocumented) + updateOne>(state: PreventAny, update: PayloadAction>): S; + // (undocumented) + upsertMany>(state: PreventAny, entities: readonly T[] | Record): S; + // (undocumented) + upsertMany>(state: PreventAny, entities: PayloadAction>): S; + // (undocumented) + upsertOne>(state: PreventAny, entity: T): S; + // (undocumented) + upsertOne>(state: PreventAny, entity: PayloadAction): S; } // @public (undocumented) -export interface EntityState { - // (undocumented) - entities: Dictionary - // (undocumented) - ids: EntityId[] +export function findNonSerializableValue(value: unknown, path?: string, isSerializable?: (value: unknown) => boolean, getEntries?: (value: unknown) => [string, any][], ignoredPaths?: readonly string[]): NonSerializableValue | false; + +// @public (undocumented) +export interface ForkedTask { + cancel(): void; + result: Promise>; } // @public (undocumented) -export interface EntityStateAdapter { - // (undocumented) - addMany>( - state: PreventAny, - entities: readonly T[] | Record - ): S - // (undocumented) - addMany>( - state: PreventAny, - entities: PayloadAction> - ): S - // (undocumented) - addOne>(state: PreventAny, entity: T): S - // (undocumented) - addOne>( - state: PreventAny, - action: PayloadAction - ): S - // (undocumented) - removeAll>(state: PreventAny): S - // (undocumented) - removeMany>( - state: PreventAny, - keys: readonly EntityId[] - ): S - // (undocumented) - removeMany>( - state: PreventAny, - keys: PayloadAction - ): S - // (undocumented) - removeOne>(state: PreventAny, key: EntityId): S - // (undocumented) - removeOne>( - state: PreventAny, - key: PayloadAction - ): S - // (undocumented) - setAll>( - state: PreventAny, - entities: readonly T[] | Record - ): S - // (undocumented) - setAll>( - state: PreventAny, - entities: PayloadAction> - ): S - // (undocumented) - setMany>( - state: PreventAny, - entities: readonly T[] | Record - ): S - // (undocumented) - setMany>( - state: PreventAny, - entities: PayloadAction> - ): S - // (undocumented) - setOne>(state: PreventAny, entity: T): S - // (undocumented) - setOne>( - state: PreventAny, - action: PayloadAction - ): S - // (undocumented) - updateMany>( - state: PreventAny, - updates: ReadonlyArray> - ): S - // (undocumented) - updateMany>( - state: PreventAny, - updates: PayloadAction>> - ): S - // (undocumented) - updateOne>( - state: PreventAny, - update: Update - ): S - // (undocumented) - updateOne>( - state: PreventAny, - update: PayloadAction> - ): S - // (undocumented) - upsertMany>( - state: PreventAny, - entities: readonly T[] | Record - ): S - // (undocumented) - upsertMany>( - state: PreventAny, - entities: PayloadAction> - ): S - // (undocumented) - upsertOne>(state: PreventAny, entity: T): S - // (undocumented) - upsertOne>( - state: PreventAny, - entity: PayloadAction - ): S +export interface ForkedTaskAPI { + delay(timeoutMs: number): Promise; + pause(waitFor: Promise): Promise; + signal: AbortSignal; } // @public (undocumented) -export function findNonSerializableValue( - value: unknown, - path?: string, - isSerializable?: (value: unknown) => boolean, - getEntries?: (value: unknown) => [string, any][], - ignoredPaths?: readonly string[] -): NonSerializableValue | false +export type ForkedTaskExecutor = AsyncTaskExecutor | SyncTaskExecutor; export { freeze } // @public @deprecated -export function getDefaultMiddleware< - S = any, - O extends Partial = { - thunk: true - immutableCheck: true - serializableCheck: true - } ->(options?: O): MiddlewareArray | ThunkMiddlewareFor> +export function getDefaultMiddleware = { + thunk: true; + immutableCheck: true; + serializableCheck: true; +}>(options?: O): MiddlewareArray], never>>; // @public -export function getType( - actionCreator: PayloadActionCreator -): T +export function getType(actionCreator: PayloadActionCreator): T; // @public (undocumented) -export type IdSelector = (model: T) => EntityId +export type IdSelector = (model: T) => Id; // @public export interface ImmutableStateInvariantMiddlewareOptions { - // (undocumented) - ignore?: string[] - ignoredPaths?: string[] - isImmutable?: IsImmutableFunc - warnAfter?: number + // (undocumented) + ignore?: string[]; + ignoredPaths?: string[]; + isImmutable?: IsImmutableFunc; + warnAfter?: number; } // @public -export function isAllOf, ...Matcher[]]>( - ...matchers: Matchers -): ( - action: any -) => action is UnionToIntersection> +export function isAllOf, ...Matcher[]]>(...matchers: Matchers): (action: any) => action is UnionToIntersection>; // @public -export function isAnyOf, ...Matcher[]]>( - ...matchers: Matchers -): (action: any) => action is ActionFromMatcher +export function isAnyOf, ...Matcher[]]>(...matchers: Matchers): (action: any) => action is ActionFromMatcher; // @public -export function isAsyncThunkAction(): ( - action: any -) => action is UnknownAsyncThunkAction +export function isAsyncThunkAction(): (action: any) => action is UnknownAsyncThunkAction; // @public -export function isAsyncThunkAction< - AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]] ->( - ...asyncThunks: AsyncThunks -): (action: any) => action is ActionsFromAsyncThunk +export function isAsyncThunkAction(...asyncThunks: AsyncThunks): (action: any) => action is ActionsFromAsyncThunk; // @public -export function isAsyncThunkAction( - action: any -): action is UnknownAsyncThunkAction +export function isAsyncThunkAction(action: any): action is UnknownAsyncThunkAction; export { isDraft } // @public -export function isFulfilled(): ( - action: any -) => action is UnknownAsyncThunkFulfilledAction +export function isFulfilled(): (action: any) => action is UnknownAsyncThunkFulfilledAction; // @public -export function isFulfilled< - AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]] ->( - ...asyncThunks: AsyncThunks -): (action: any) => action is FulfilledActionFromAsyncThunk +export function isFulfilled(...asyncThunks: AsyncThunks): (action: any) => action is FulfilledActionFromAsyncThunk; // @public -export function isFulfilled( - action: any -): action is UnknownAsyncThunkFulfilledAction +export function isFulfilled(action: any): action is UnknownAsyncThunkFulfilledAction; // @public -export function isImmutableDefault(value: unknown): boolean +export function isImmutableDefault(value: unknown): boolean; // @public -export function isPending(): ( - action: any -) => action is UnknownAsyncThunkPendingAction +export function isPending(): (action: any) => action is UnknownAsyncThunkPendingAction; // @public -export function isPending< - AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]] ->( - ...asyncThunks: AsyncThunks -): (action: any) => action is PendingActionFromAsyncThunk +export function isPending(...asyncThunks: AsyncThunks): (action: any) => action is PendingActionFromAsyncThunk; // @public -export function isPending(action: any): action is UnknownAsyncThunkPendingAction +export function isPending(action: any): action is UnknownAsyncThunkPendingAction; // @public -export function isPlain(val: any): boolean +export function isPlain(val: any): boolean; // @public -export function isPlainObject(value: unknown): value is object +export function isPlainObject(value: unknown): value is object; // @public -export function isRejected(): ( - action: any -) => action is UnknownAsyncThunkRejectedAction +export function isRejected(): (action: any) => action is UnknownAsyncThunkRejectedAction; // @public -export function isRejected< - AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]] ->( - ...asyncThunks: AsyncThunks -): (action: any) => action is RejectedActionFromAsyncThunk +export function isRejected(...asyncThunks: AsyncThunks): (action: any) => action is RejectedActionFromAsyncThunk; // @public -export function isRejected( - action: any -): action is UnknownAsyncThunkRejectedAction +export function isRejected(action: any): action is UnknownAsyncThunkRejectedAction; // @public -export function isRejectedWithValue(): ( - action: any -) => action is UnknownAsyncThunkRejectedAction +export function isRejectedWithValue(): (action: any) => action is UnknownAsyncThunkRejectedAction; // @public -export function isRejectedWithValue< - AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]] ->( - ...asyncThunks: AsyncThunks -): ( - action: any -) => action is RejectedWithValueActionFromAsyncThunk +export function isRejectedWithValue(...asyncThunks: AsyncThunks): (action: any) => action is RejectedWithValueActionFromAsyncThunk; // @public -export function isRejectedWithValue( - action: any -): action is UnknownAsyncThunkRejectedAction +export function isRejectedWithValue(action: any): action is UnknownAsyncThunkRejectedAction; + +// @public (undocumented) +export type ListenerEffect, ExtraArgument = unknown> = (action: Action, api: ListenerEffectAPI) => void | Promise; // @public (undocumented) -export class MiddlewareArray< - Middlewares extends Middleware -> extends Array { - // (undocumented) - static get [Symbol.species](): any - constructor(arrayLength?: number) - constructor(...items: Middlewares[]) - // (undocumented) - concat>>( - items: AdditionalMiddlewares - ): MiddlewareArray - // (undocumented) - concat>>( - ...items: AdditionalMiddlewares - ): MiddlewareArray - // (undocumented) - prepend>>( - items: AdditionalMiddlewares - ): MiddlewareArray - // (undocumented) - prepend>>( - ...items: AdditionalMiddlewares - ): MiddlewareArray +export interface ListenerEffectAPI, ExtraArgument = unknown> extends MiddlewareAPI { + // (undocumented) + cancelActiveListeners: () => void; + // (undocumented) + condition: ConditionFunction; + delay(timeoutMs: number): Promise; + // (undocumented) + extra: ExtraArgument; + fork(executor: ForkedTaskExecutor): ForkedTask; + getOriginalState: () => State; + pause(promise: Promise): Promise; + signal: AbortSignal; + // (undocumented) + subscribe(): void; + // (undocumented) + take: TakePattern; + // (undocumented) + unsubscribe(): void; } // @public -export const miniSerializeError: (value: any) => SerializedError +export interface ListenerErrorHandler { + // (undocumented) + (error: unknown, errorInfo: ListenerErrorInfo): void; +} // @public (undocumented) -export let nanoid: (size?: number) => string +export type ListenerMiddleware = ThunkDispatch, ExtraArgument = unknown> = Middleware<{ + (action: Action<'listenerMiddleware/add'>): UnsubscribeListener; +}, State, Dispatch>; + +// @public (undocumented) +export interface ListenerMiddlewareInstance = ThunkDispatch, ExtraArgument = unknown> { + clearListeners: () => void; + // (undocumented) + middleware: ListenerMiddleware; + // (undocumented) + startListening: AddListenerOverloads; + // (undocumented) + stopListening: RemoveListenerOverloads; +} + +// @public (undocumented) +export class MiddlewareArray[]> extends Array { + // (undocumented) + static get [Symbol.species](): any; + constructor(...items: Middlewares); + // (undocumented) + concat>>(items: AdditionalMiddlewares): MiddlewareArray<[...Middlewares, ...AdditionalMiddlewares]>; + // (undocumented) + concat>>(...items: AdditionalMiddlewares): MiddlewareArray<[...Middlewares, ...AdditionalMiddlewares]>; + // (undocumented) + prepend>>(items: AdditionalMiddlewares): MiddlewareArray<[...AdditionalMiddlewares, ...Middlewares]>; + // (undocumented) + prepend>>(...items: AdditionalMiddlewares): MiddlewareArray<[...AdditionalMiddlewares, ...Middlewares]>; +} + +// @public +export const miniSerializeError: (value: any) => SerializedError; + +// @public (undocumented) +export let nanoid: (size?: number) => string; export { original } @@ -692,150 +504,163 @@ export { OutputSelector } export { ParametricSelector } // @public -export type PayloadAction< - P = void, - T extends string = string, - M = never, - E = never -> = { - payload: P - type: T -} & ([M] extends [never] - ? {} - : { - meta: M - }) & - ([E] extends [never] - ? {} - : { - error: E - }) - -// @public -export type PayloadActionCreator< - P = void, - T extends string = string, - PA extends PrepareAction