RxJS powered Redux state management for Angular applications
npx @tessl/cli install tessl/npm-ngrx--store@20.0.0NgRx Store is a comprehensive state management library for Angular applications that implements the Redux pattern using RxJS. It provides a centralized, immutable state container with reactive state management, type-safe actions, memoized selectors, and comprehensive development tools integration.
npm install @ngrx/store@angular/core ^20.0.0, rxjs ^6.5.3 || ^7.5.0import { Store, createAction, createReducer, createSelector, on } from "@ngrx/store";For testing:
import { provideMockStore, MockStore } from "@ngrx/store/testing";import { Component, inject } from "@angular/core";
import { Store, createAction, createReducer, createSelector, on, props } from "@ngrx/store";
// Define actions
export const increment = createAction('[Counter] Increment');
export const decrement = createAction('[Counter] Decrement');
export const reset = createAction('[Counter] Reset');
export const setValue = createAction(
'[Counter] Set Value',
props<{ value: number }>()
);
// Define state
interface CounterState {
count: number;
}
const initialState: CounterState = { count: 0 };
// Create reducer
const counterReducer = createReducer(
initialState,
on(increment, (state) => ({ ...state, count: state.count + 1 })),
on(decrement, (state) => ({ ...state, count: state.count - 1 })),
on(reset, () => initialState),
on(setValue, (state, { value }) => ({ ...state, count: value }))
);
// Create selector
const selectCount = createSelector(
(state: { counter: CounterState }) => state.counter,
(counter) => counter.count
);
// Use in component
@Component({
selector: 'app-counter',
template: `
<div>Count: {{ count() }}</div>
<button (click)="increment()">+</button>
<button (click)="decrement()">-</button>
<button (click)="reset()">Reset</button>
`
})
export class CounterComponent {
private store = inject(Store);
count = this.store.selectSignal(selectCount);
increment() { this.store.dispatch(increment()); }
decrement() { this.store.dispatch(decrement()); }
reset() { this.store.dispatch(reset()); }
}NgRx Store is built around several key architectural patterns:
Core reactive state container that provides dispatch and selection capabilities. Extends Observable for reactive state access with Angular Signals support.
class Store<T = object> extends Observable<T> implements Observer<Action> {
selectSignal<K>(selector: (state: T) => K, options?: SelectSignalOptions<K>): Signal<K>;
dispatch<V extends Action>(action: V): void;
dispatch<V extends () => Action>(dispatchFn: V, config?: { injector: Injector }): EffectRef;
select<K>(mapFn: (state: T) => K): Observable<K>;
addReducer<State, Actions extends Action>(key: string, reducer: ActionReducer<State, Actions>): void;
removeReducer<Key extends Extract<keyof T, string>>(key: Key): void;
}Type-safe action creation with payload validation and action group organization. Supports both individual actions and grouped actions with shared sources.
function createAction<T extends string>(type: T): ActionCreator<T, () => Action<T>>;
function createAction<T extends string, P extends object>(
type: T,
config: ActionCreatorProps<P>
): ActionCreator<T, (props: P) => P & Action<T>>;
function createActionGroup<Source extends string, Events>(
config: ActionGroupConfig<Source, Events>
): ActionGroup<Source, Events>;
function props<P>(): ActionCreatorProps<P>;Simplified reducer creation with type-safe action handling using the on function pattern. Supports initial state and multiple action handlers.
function createReducer<State>(
initialState: State,
...ons: ReducerTypes<State, any>[]
): ActionReducer<State>;
function on<State, Creators extends readonly ActionCreator[]>(
...args: [...creators: Creators, reducer: OnReducer<State, Creators>]
): ReducerTypes<State, Creators>;Memoized state selection with composition and performance optimization. Supports feature selectors, composed selectors, and custom memoization strategies.
function createSelector<Selectors extends readonly any[], Result>(
selectors: [...Selectors],
projector: (...args: SelectorResults<Selectors>) => Result
): MemoizedSelector<any, Result>;
function createFeatureSelector<T, K extends keyof T>(
featureKey: K
): MemoizedSelector<T, T[K]>;
function createSelectorFactory<T, V>(
memoize: MemoizeFn
): SelectorFactory<T, V>;Modular state organization with lazy-loaded features and automatic selector generation. Supports feature state isolation and dynamic loading.
function createFeature<FeatureName extends string, FeatureState>(
config: FeatureConfig<FeatureName, FeatureState>
): Feature<FeatureName, FeatureState>;
interface FeatureConfig<FeatureName extends string, FeatureState> {
name: FeatureName;
reducer: ActionReducer<FeatureState>;
}NgModule-based configuration for traditional Angular applications with root and feature module support.
class StoreModule {
static forRoot<T, V extends Action = Action>(
reducers?: ActionReducerMap<T, V>,
config?: RootStoreConfig<T, V>
): ModuleWithProviders<StoreRootModule>;
static forFeature<T, V extends Action = Action>(
featureName: string,
reducers: ActionReducerMap<T, V> | ActionReducer<T, V>,
config?: StoreConfig<T, V>
): ModuleWithProviders<StoreFeatureModule>;
}Modern standalone application support with environment providers for root and feature state configuration.
function provideStore<T, V extends Action = Action>(
reducers?: ActionReducerMap<T, V>,
config?: RootStoreConfig<T, V>
): EnvironmentProviders;
function provideState<T, V extends Action = Action>(
featureName: string,
reducers: ActionReducerMap<T, V> | ActionReducer<T, V>,
config?: StoreConfig<T, V>
): EnvironmentProviders;Comprehensive testing support with mock store implementations and selector overrides for unit testing.
function provideMockStore<T>(config?: MockStoreConfig<T>): Provider[];
function createMockStore<T>(config?: MockStoreConfig<T>): MockStore<T>;
class MockStore<T> extends Store<T> {
overrideSelector<Result>(selector: MemoizedSelector<any, Result>, value: Result): void;
refreshState(): void;
setState(nextState: T): void;
}Essential type definitions for NgRx Store integration and extension.
/**
* Base action type with required type property
*/
interface Action<Type extends string = string> {
type: Type;
}
/**
* Infers action type from action creator
*/
type ActionType<A> = A extends ActionCreator<infer T, infer C>
? ReturnType<C> & { type: T }
: never;
/**
* Store feature configuration interface
*/
interface StoreFeature<T, V extends Action = Action> {
key: string;
reducers: ActionReducerMap<T, V> | ActionReducer<T, V>;
reducerFactory: ActionReducerFactory<T, V>;
initialState?: InitialState<T>;
metaReducers?: MetaReducer<T, V>[];
}
/**
* Initial state type - can be partial state, factory function, or void
*/
type InitialState<T> = Partial<T> | TypeId<Partial<T>> | void;
/**
* Factory function type for initial state
*/
type TypeId<T> = () => T;Type utilities for compile-time validation and type safety.
/**
* Compile-time check to prevent dispatching action creators directly
*/
type CreatorsNotAllowedCheck<T> = T extends ActionCreator
? 'Action creator is not allowed to be dispatched. Did you forget to call it?'
: unknown;
/**
* Type-level validation for disallowed properties in action payloads
*/
type NotAllowedCheck<T> = T extends any[]
? 'action creator cannot return an array'
: T extends { type: any }
? 'action creator cannot return an object with a property named `type`'
: T extends Record<string, never>
? 'action creator cannot return an empty object'
: unknown;
/**
* Flattens intersection types for better IntelliSense
*/
type Prettify<T> = {
[K in keyof T]: T[K];
} & {};Core action constants used by NgRx Store internally.
/**
* Initial action dispatched when store is created
*/
const INIT: '@ngrx/store/init';
/**
* Action dispatched when reducers are updated dynamically
*/
const UPDATE: '@ngrx/store/update-reducers';Utilities for configuring NgRx in testing environments.
/**
* Sets NgRx mock environment flag for testing
* @param value - Whether to enable mock environment
*/
function setNgrxMockEnvironment(value: boolean): void;
/**
* Checks if NgRx is running in mock environment
* @returns True if in mock environment, false otherwise
*/
function isNgrxMockEnvironment(): boolean;Usage Examples:
// Type-safe action handling
interface AppState {
user: UserState;
todos: TodoState;
}
// Using StoreFeature for lazy loading
const userFeature: StoreFeature<UserState> = {
key: 'user',
reducers: userReducer,
reducerFactory: createReducerFactory(combineReducers),
initialState: { id: null, name: '', email: '' },
metaReducers: [loggingMetaReducer]
};
// Mock environment setup for testing
beforeEach(() => {
setNgrxMockEnvironment(true);
// Test setup...
});
afterEach(() => {
setNgrxMockEnvironment(false);
});
// Type validation at compile time
const validAction = increment(); // ✓ Valid
// const invalidAction = increment; // ✗ Compile error - CreatorsNotAllowedCheck