0
# @ngrx/core
1
2
@ngrx/core provides essential RxJS operators and utilities for the NgRx platform, a reactive state management library for Angular applications. It includes state selection operators with automatic distinctness checking, Angular zone management operators, and functional composition utilities that integrate seamlessly with RxJS streams.
3
4
## Package Information
5
6
- **Package Name**: @ngrx/core
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install @ngrx/core`
10
11
## Core Imports
12
13
```typescript
14
import { select, enterZone, leaveZone, compose } from "@ngrx/core";
15
```
16
17
For CommonJS:
18
19
```javascript
20
const { select, enterZone, leaveZone, compose } = require("@ngrx/core");
21
```
22
23
## Basic Usage
24
25
```typescript
26
import { Observable } from "rxjs";
27
import { select, enterZone, leaveZone, compose } from "@ngrx/core";
28
29
// State selection with automatic distinctness
30
const state$ = new Observable(/* state stream */);
31
const todoFilter$ = state$.let(select('filter'));
32
const todoTitle$ = state$.let(select('todos', 'a', 'title'));
33
const mappedState$ = state$.let(select(state => state.user.name));
34
35
// Zone management
36
const zone = {
37
run: (fn) => fn(),
38
runOutsideAngular: (fn) => fn()
39
};
40
const enterZoned$ = stream$.let(enterZone(zone));
41
const leaveZoned$ = stream$.let(leaveZone(zone));
42
43
// Function composition
44
const processData = compose(
45
(data) => data.toUpperCase(),
46
(data) => data.trim(),
47
(data) => data.replace(/\\s+/g, ' ')
48
);
49
const result = processData(" hello world ");
50
```
51
52
## Capabilities
53
54
### State Selection
55
56
The select operator extracts specific slices of state with automatic distinctness checking to prevent unnecessary re-renders.
57
58
```typescript { .api }
59
/**
60
* Select operator for extracting state slices with automatic distinctness
61
* Used with Observable.prototype.let() method
62
* @param pathOrMapFn - String path or mapping function
63
* @param paths - Additional path segments for nested property access
64
* @returns Operator function for use with .let()
65
*/
66
function select<T, R>(pathOrMapFn: string | ((state: T) => R), ...paths: string[]): Observable<R>;
67
68
interface SelectSignature<T> {
69
<R>(...paths: string[]): Observable<R>;
70
<R>(mapFn: (state: T) => R): Observable<R>;
71
}
72
```
73
74
**Usage Examples:**
75
76
```typescript
77
import { Observable } from "rxjs";
78
import { select } from "@ngrx/core";
79
80
const state = {
81
todos: { a: { title: 'First Todo' }, b: { title: 'Second Todo' } },
82
filter: 'all'
83
};
84
85
// String path selection
86
const filter$ = Observable.of(state).let(select('filter'));
87
88
// Nested path selection
89
const todoTitle$ = Observable.of(state).let(select('todos', 'a', 'title'));
90
91
// Function-based selection
92
const todoB$ = Observable.of(state).let(select(s => s.todos.b.title));
93
```
94
95
### Zone Entry Management
96
97
The enterZone operator ensures emissions are executed within Angular's zone context for proper change detection.
98
99
```typescript { .api }
100
/**
101
* Enter Angular zone for emissions to trigger change detection
102
* Used with Observable.prototype.let() method
103
* @param zone - Zone-like object with run method
104
* @returns Operator function for use with .let()
105
*/
106
function enterZone<T>(zone: ZoneInterface): Observable<T>;
107
108
interface EnterZoneSignature<T> {
109
(zone: ZoneInterface): Observable<T>;
110
}
111
112
interface ZoneInterface {
113
run: (fn: any) => any;
114
}
115
```
116
117
### Zone Exit Management
118
119
The leaveZone operator ensures emissions are executed outside Angular's zone context to avoid triggering change detection.
120
121
```typescript { .api }
122
/**
123
* Leave Angular zone for emissions to avoid change detection
124
* Used with Observable.prototype.let() method
125
* @param zone - Zone-like object with runOutsideAngular method
126
* @returns Operator function for use with .let()
127
*/
128
function leaveZone<T>(zone: NgZoneInterface): Observable<T>;
129
130
interface LeaveZoneSignature<T> {
131
(zone: NgZoneInterface): Observable<T>;
132
}
133
134
interface NgZoneInterface {
135
runOutsideAngular: (fn: any) => any;
136
}
137
```
138
139
### Function Composition
140
141
The compose utility provides type-safe functional composition for chaining transformation functions.
142
143
```typescript { .api }
144
/**
145
* Compose functions right-to-left with full type safety
146
* @param functions - Functions to compose, applied right-to-left
147
* @returns Composed function that applies all transformations
148
*/
149
const compose: ComposeSignature;
150
151
interface ComposeSignature {
152
<A>(): (i: A) => A;
153
<A, B>(b: (i: A) => B): (i: A) => B;
154
<A, B, C>(c: (i: B) => C, b: (i: A) => B): (i: A) => C;
155
<A, B, C, D>(d: (i: C) => D, c: (i: B) => C, b: (i: A) => B): (i: A) => D;
156
<A, B, C, D, E>(e: (i: D) => E, d: (i: C) => D, c: (i: B) => C, b: (i: A) => B): (i: A) => E;
157
<A, B, C, D, E, F>(f: (i: E) => F, e: (i: D) => E, d: (i: C) => D, c: (i: B) => C, b: (i: A) => B): (i: A) => F;
158
(...fns: any[]): (input: any) => any;
159
}
160
```
161
162
**Usage Example:**
163
164
```typescript
165
import { compose } from "@ngrx/core";
166
167
const double = (i: number) => 2 * i;
168
const add = (amount: number) => (i: number) => i + amount;
169
const toString = (i: number) => `${i}`;
170
171
// Compose functions right-to-left
172
const processNumber = compose(toString, add(3), double);
173
const result = processNumber(3); // "9" (3 * 2 + 3 = "9")
174
175
// Identity function with no arguments
176
const identity = compose();
177
console.log(identity(42)); // 42
178
```
179
180
## Observable Prototype Extensions
181
182
For users who prefer prototype-style operators, @ngrx/core provides optional prototype extensions:
183
184
```typescript
185
// Import to add methods to Observable.prototype
186
import "@ngrx/core/src/add/operator/select";
187
import "@ngrx/core/src/add/operator/enterZone";
188
import "@ngrx/core/src/add/operator/leaveZone";
189
190
// Now available as methods
191
state$.select('todos');
192
stream$.enterZone(zone);
193
stream$.leaveZone(zone);
194
```
195
196
## Types
197
198
```typescript { .api }
199
// Internal operator implementation classes (not directly exposed)
200
class EnterZoneOperator<T> implements Operator<T, T> {
201
constructor(private _zone: ZoneInterface);
202
call(subscriber: Subscriber<T>, source: any): any;
203
}
204
205
class LeaveZoneOperator<T> implements Operator<T, T> {
206
constructor(private _zone: NgZoneInterface);
207
call(subscriber: Subscriber<T>, source: any): any;
208
}
209
210
// Utility subject for immediate value emission
211
class SyncSubject<T> extends ReplaySubject<T> {
212
constructor(value: T);
213
}
214
```
215
216
## Error Handling
217
218
The select operator includes built-in error handling:
219
220
- **TypeError**: Thrown when `pathOrMapFn` is neither a string nor a function
221
- **RxJS Error Propagation**: All operators follow standard RxJS error propagation patterns
222
223
## Dependencies
224
225
- **RxJS**: ^5.0.0-beta.12 (peer dependency)
226
- Uses RxJS operators: `pluck`, `map`, `distinctUntilChanged`
227
- Uses RxJS classes: `Observable`, `Operator`, `Subscriber`, `ReplaySubject`