Skip to content

[DRAFT] Experiment: Add "indices" to entity adapter #948

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
7 changes: 3 additions & 4 deletions etc/redux-toolkit.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,7 @@ export function createAsyncThunk<Returned, ThunkArg = void, ThunkApiConfig exten
export const createDraftSafeSelector: typeof createSelector;

// @public (undocumented)
export function createEntityAdapter<T>(options?: {
selectId?: IdSelector<T>;
sortComparer?: false | Comparer<T>;
}): EntityAdapter<T>;
export function createEntityAdapter<T>(options?: EntityDefinition<T>): EntityAdapter<T>;

// @public
export function createImmutableStateInvariantMiddleware(options?: ImmutableStateInvariantMiddlewareOptions): Middleware;
Expand Down Expand Up @@ -230,6 +227,8 @@ export interface EntityState<T> {
entities: Dictionary<T>;
// (undocumented)
ids: EntityId[];
// (undocumented)
indices: Indices<T, IndexComparers<T>>;
}

// @public (undocumented)
Expand Down
21 changes: 12 additions & 9 deletions src/entities/create_adapter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { EntityDefinition, Comparer, IdSelector, EntityAdapter } from './models'
import {
EntityDefinition,
Comparer,
EntityAdapter,
IndexComparers
} from './models'
import { createInitialStateFactory } from './entity_state'
import { createSelectorsFactory } from './state_selectors'
import { createSortedStateAdapter } from './sorted_state_adapter'
Expand All @@ -10,22 +15,20 @@ import { createUnsortedStateAdapter } from './unsorted_state_adapter'
*
* @public
*/

export function createEntityAdapter<T>(
options: {
selectId?: IdSelector<T>
sortComparer?: false | Comparer<T>
} = {}
options?: EntityDefinition<T>
): EntityAdapter<T> {
const { selectId, sortComparer }: EntityDefinition<T> = {
sortComparer: false,
const { selectId, sortComparer, indices = {} as IndexComparers<T> } = {
sortComparer: false as const,
selectId: (instance: any) => instance.id,
...options
}

const stateFactory = createInitialStateFactory<T>()
const stateFactory = createInitialStateFactory<T, IndexComparers<T>>(indices)
const selectorsFactory = createSelectorsFactory<T>()
const stateAdapter = sortComparer
? createSortedStateAdapter(selectId, sortComparer)
? createSortedStateAdapter(selectId, sortComparer as Comparer<T>, indices)
: createUnsortedStateAdapter(selectId)

return {
Expand Down
18 changes: 16 additions & 2 deletions src/entities/entity_state.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ import { BookModel } from './fixtures/book'
describe('Entity State', () => {
let adapter: EntityAdapter<BookModel>

const adapter2 = createEntityAdapter<BookModel>({
selectId: (book: BookModel) => book.id,
indices: {
// TODO These should be BookModel, not unknown
id: (a, b) => a.id.localeCompare(b.id)
}
})

const tempState = adapter2.getInitialState()
// TODO should be an empty array
console.log(tempState.indices.id)

beforeEach(() => {
adapter = createEntityAdapter({
selectId: (book: BookModel) => book.id
Expand All @@ -17,7 +29,8 @@ describe('Entity State', () => {

expect(initialState).toEqual({
ids: [],
entities: {}
entities: {},
indices: {}
})
})

Expand All @@ -29,7 +42,8 @@ describe('Entity State', () => {
expect(initialState).toEqual({
...additionalProperties,
ids: [],
entities: {}
entities: {},
indices: {}
})
})

Expand Down
24 changes: 19 additions & 5 deletions src/entities/entity_state.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,33 @@
import { EntityState } from './models'
import { EntityState, IndexComparers, Indices } from './models'

export function getInitialEntityState<V, IC extends IndexComparers<V>>(
indexComparers: IC
): EntityState<V> {
const indices = {} as Indices<V, IC>

for (let key in indexComparers) {
indices[key] = []
}

export function getInitialEntityState<V>(): EntityState<V> {
return {
ids: [],
entities: {}
entities: {},
indices
}
}

export function createInitialStateFactory<V>() {
export function createInitialStateFactory<V, IC extends IndexComparers<V>>(
indexComparers: IC
) {
function getInitialState(): EntityState<V>
function getInitialState<S extends object>(
additionalState: S
): EntityState<V> & S
function getInitialState(additionalState: any = {}): any {
return Object.assign(getInitialEntityState(), additionalState)
return Object.assign(
getInitialEntityState(indexComparers as any),
additionalState
)
}

return { getInitialState }
Expand Down
Loading