Skip to content

Function: createEntityAdapter()

createEntityAdapter<Entity, Id, State>(): <S, R, Filters, Sorters>(adapter, options?) => object & BasicAdapterMethods<State> & { [K in string as K extends "selectors" | "set" ? never : PrefixedAfterVerb<Exclude<K, "set" | "reset">, "all" | Filters[number]>]: R[K] extends (state: any, payload: any, initialState: any) => any ? (state: State, payload: Parameters<any[any]>[1] extends void ? void : Parameters<any[any]>[1], initialState: State) => State : never } & { [K in string as K extends "selectors" | "set" ? never : PrefixedAfterVerb<K, "one">]: R[K] extends (state: any, payload: any, initialState: any) => any ? (state: State, payload: Parameters<any[any]>[1] extends void ? Extract<Entity[Id], Index> : [Extract<Entity[Id], Index>, Parameters<any[any]>[1]], initialState: State) => State : never } & { [K in string as K extends "selectors" | "set" ? never : PrefixedAfterVerb<K, "many">]: R[K] extends (state: any, payload: any, initialState: any) => any ? (state: State, payload: Parameters<any[any]>[1] extends void ? Extract<Entity[Id], Index>[] : [Extract<Entity[Id], Index>, Parameters<any[any]>[1]][], initialState: State) => State : never } & object

Defined in: adapters/src/lib/create-entity-adapter.function.ts:309

Creates an adapter for normalized entity state from an adapter for one entity.

The result includes collection reactions such as addOne, setAll, and removeMany. Reactions from the entity adapter are expanded for one, many, all, and any configured filters. Entity selectors can also become filters or sorters for the collection.

Entities use their id field by default. For another ID field, pass its key as the second type argument and add an id selector to the entity adapter.

Example: Filters and sorting

typescript
import { createAdapter } from '@state-adapt/core';
import {
  createEntityAdapter,
  createEntityState,
  EntityState,
} from '@state-adapt/core/adapters';

interface Todo {
  todoId: string;
  title: string;
  priority: number;
  done: boolean;
}

const todoAdapter = createAdapter<Todo>()({
  toggleDone: todo => ({ ...todo, done: !todo.done }),
  selectors: {
    id: todo => todo.todoId,
    done: todo => todo.done,
    priority: todo => todo.priority,
  },
});

const createTodosAdapter = createEntityAdapter<Todo, 'todoId'>();

export const todosAdapter = createTodosAdapter(todoAdapter, {
  filters: ['done'],
  sorters: ['priority'],
});

type TodosState = EntityState<Todo, 'todoId'>;

export const initialTodosState: TodosState = todosAdapter.setAll(
  createEntityState<Todo, 'todoId'>(),
  [
    { todoId: 'tests', title: 'Write tests', priority: 2, done: true },
    { todoId: 'docs', title: 'Write docs', priority: 1, done: false },
  ],
);

Usage with React

tsx
import { adapt, useStore } from '@state-adapt/react';
import { initialTodosState, todosAdapter } from './todos.adapter';

const todosStore = adapt(initialTodosState, todosAdapter);

export function CompletedTodos() {
  const [todos, actions] = useStore(todosStore);

  return (
    <ul>
      {todos.doneByPriority.map(todo => (
        <li key={todo.todoId}>
          <button onClick={() => actions.toggleOneDone(todo.todoId)}>
            {todo.title}
          </button>
        </li>
      ))}
    </ul>
  );
}

Usage with Angular

angular-ts
import { Component } from '@angular/core';
import { adapt } from '@state-adapt/angular';
import { initialTodosState, todosAdapter } from './todos.adapter';

@Component({
  standalone: true,
  selector: 'app-completed-todos',
  template: `
    <ul>
      @for (todo of todos.doneByPriority(); track todo.todoId) {
        <li>
          <button (click)="todos.toggleOneDone(todo.todoId)">
            {{ todo.title }}
          </button>
        </li>
      }
    </ul>
  `,
})
export class CompletedTodosComponent {
  todos = adapt(initialTodosState, todosAdapter);
}

Running examples

Type Parameters

Entity

Entity

Id

Id extends string | number | symbol = DefaultId<Entity>

State

State extends EntityState<Entity, Id> = EntityState<Entity, Id>

Returns

<S, R, Filters, Sorters>(adapter, options?): object & BasicAdapterMethods<State> & { [K in string as K extends "selectors" | "set" ? never : PrefixedAfterVerb<Exclude<K, "set" | "reset">, "all" | Filters[number]>]: R[K] extends (state: any, payload: any, initialState: any) => any ? (state: State, payload: Parameters<any[any]>[1] extends void ? void : Parameters<any[any]>[1], initialState: State) => State : never } & { [K in string as K extends "selectors" | "set" ? never : PrefixedAfterVerb<K, "one">]: R[K] extends (state: any, payload: any, initialState: any) => any ? (state: State, payload: Parameters<any[any]>[1] extends void ? Extract<Entity[Id], Index> : [Extract<Entity[Id], Index>, Parameters<any[any]>[1]], initialState: State) => State : never } & { [K in string as K extends "selectors" | "set" ? never : PrefixedAfterVerb<K, "many">]: R[K] extends (state: any, payload: any, initialState: any) => any ? (state: State, payload: Parameters<any[any]>[1] extends void ? Extract<Entity[Id], Index>[] : [Extract<Entity[Id], Index>, Parameters<any[any]>[1]][], initialState: State) => State : never } & object

Type Parameters

S

S extends Selectors<Entity>

R

R extends ReactionsWithSelectors<Entity, S>

Filters

Filters extends Extract<keyof S, string>[] = never[]

Sorters

Sorters extends Extract<keyof S, string>[] = never[]

Parameters

adapter

Adapter<Entity, S, R>

options?

filters?

Filters

sorters?

Sorters

useCache?

boolean

Returns

object & BasicAdapterMethods<State> & { [K in string as K extends "selectors" | "set" ? never : PrefixedAfterVerb<Exclude<K, "set" | "reset">, "all" | Filters[number]>]: R[K] extends (state: any, payload: any, initialState: any) => any ? (state: State, payload: Parameters<any[any]>[1] extends void ? void : Parameters<any[any]>[1], initialState: State) => State : never } & { [K in string as K extends "selectors" | "set" ? never : PrefixedAfterVerb<K, "one">]: R[K] extends (state: any, payload: any, initialState: any) => any ? (state: State, payload: Parameters<any[any]>[1] extends void ? Extract<Entity[Id], Index> : [Extract<Entity[Id], Index>, Parameters<any[any]>[1]], initialState: State) => State : never } & { [K in string as K extends "selectors" | "set" ? never : PrefixedAfterVerb<K, "many">]: R[K] extends (state: any, payload: any, initialState: any) => any ? (state: State, payload: Parameters<any[any]>[1] extends void ? Extract<Entity[Id], Index>[] : [Extract<Entity[Id], Index>, Parameters<any[any]>[1]][], initialState: State) => State : never } & object