@angular/forms 21.1.0-next.1 → 21.1.0-next.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,11 @@
1
1
  /**
2
- * @license Angular v21.1.0-next.1
2
+ * @license Angular v21.1.0-next.3
3
3
  * (c) 2010-2025 Google LLC. https://angular.dev/
4
4
  * License: MIT
5
5
  */
6
6
 
7
7
  import * as i0 from '@angular/core';
8
- import { InjectionToken, ɵControl as _Control, ɵCONTROL as _CONTROL, ɵɵcontrolCreate as __controlCreate, ɵcontrolUpdate as _controlUpdate, ɵInteropControl as _InteropControl, ɵFieldState as _FieldState, Signal, Provider, WritableSignal, DestroyableInjector, Injector } from '@angular/core';
8
+ import { InjectionToken, Injector, ɵCONTROL as _CONTROL, ɵɵcontrolCreate as __controlCreate, ɵcontrolUpdate as _controlUpdate, Signal, ɵFieldState as _FieldState, Provider, WritableSignal, DestroyableInjector } from '@angular/core';
9
9
  import * as _angular_forms from '@angular/forms';
10
10
  import { NgControl, AbstractControl, ValidationErrors, FormControlStatus, ControlValueAccessor, ValidatorFn } from '@angular/forms';
11
11
  import { StandardSchemaV1 } from '@standard-schema/spec';
@@ -68,1007 +68,1044 @@ declare const FIELD: InjectionToken<Field<unknown>>;
68
68
  * @category control
69
69
  * @experimental 21.0.0
70
70
  */
71
- declare class Field<T> implements _Control<T> {
72
- private readonly injector;
73
- private config;
74
- readonly classes: (readonly [string, i0.Signal<boolean>])[];
71
+ declare class Field<T> {
72
+ readonly element: HTMLElement;
73
+ readonly injector: Injector;
75
74
  readonly field: i0.InputSignal<FieldTree<T>>;
76
75
  readonly state: i0.Signal<[T] extends [_angular_forms.AbstractControl<any, any, any>] ? CompatFieldState<T, string | number> : FieldState<T, string | number>>;
77
76
  readonly [_CONTROL]: {
78
77
  readonly create: typeof __controlCreate;
79
78
  readonly update: typeof _controlUpdate;
80
79
  };
80
+ private config;
81
81
  /** Any `ControlValueAccessor` instances provided on the host element. */
82
82
  private readonly controlValueAccessors;
83
83
  /** A lazily instantiated fake `NgControl`. */
84
84
  private interopNgControl;
85
- /** A `ControlValueAccessor`, if configured, for the host component. */
86
- get ɵinteropControl(): _InteropControl | undefined;
87
85
  /** Lazily instantiates a fake `NgControl` for this field. */
88
86
  protected getOrCreateNgControl(): InteropNgControl;
89
- ɵregister(): void;
90
87
  static ɵfac: i0.ɵɵFactoryDeclaration<Field<any>, never>;
91
88
  static ɵdir: i0.ɵɵDirectiveDeclaration<Field<any>, "[field]", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
92
89
  }
93
90
 
94
91
  /**
95
- * Represents metadata that may be defined on a field when it is created using a `metadata` rule
96
- * in the schema. A particular `MetadataKey` can only be defined on a particular field **once**.
92
+ * Sets a value for the {@link MetadataKey} for this field.
93
+ *
94
+ * This value is combined via a reduce operation defined by the particular key,
95
+ * since multiple rules in the schema might set values for it.
96
+ *
97
+ * @param path The target path to set the metadata for.
98
+ * @param key The metadata key
99
+ * @param logic A function that receives the `FieldContext` and returns a value for the metadata.
100
+ * @template TValue The type of value stored in the field the logic is bound to.
101
+ * @template TKey The type of metadata key.
102
+ * @template TPathKind The kind of path the logic is bound to (a root path, child path, or item of an array)
97
103
  *
98
104
  * @category logic
99
105
  * @experimental 21.0.0
100
106
  */
101
- declare class MetadataKey<TValue> {
102
- private brand;
103
- /** Use {@link createMetadataKey}. */
104
- private constructor();
105
- }
107
+ declare function metadata<TValue, TKey extends MetadataKey<any, any, any>, TPathKind extends PathKind = PathKind.Root>(path: SchemaPath<TValue, SchemaPathRules.Supported, TPathKind>, key: TKey, logic: NoInfer<LogicFn<TValue, MetadataSetterType<TKey>, TPathKind>>): TKey;
106
108
  /**
107
- * Creates a {@link MetadataKey}.
109
+ * A reducer that determines the accumulated value for a metadata key by reducing the individual
110
+ * values contributed from `metadata()` rules.
108
111
  *
109
- * @experimental 21.0.0
112
+ * @template TAcc The accumulated type of the reduce operation.
113
+ * @template TItem The type of the individual items that are reduced over.
114
+ * @experimental 21.0.2
110
115
  */
111
- declare function createMetadataKey<TValue>(): MetadataKey<TValue>;
116
+ interface MetadataReducer<TAcc, TItem> {
117
+ /** The reduce function. */
118
+ reduce: (acc: TAcc, item: TItem) => TAcc;
119
+ /** Gets the initial accumulated value. */
120
+ getInitial: () => TAcc;
121
+ }
122
+ declare const MetadataReducer: {
123
+ /** Creates a reducer that accumulates a list of its individual item values. */
124
+ readonly list: <TItem>() => MetadataReducer<TItem[], TItem | undefined>;
125
+ /** Creates a reducer that accumulates the min of its individual item values. */
126
+ readonly min: () => MetadataReducer<number | undefined, number | undefined>;
127
+ /** Creates a reducer that accumulates a the max of its individual item values. */
128
+ readonly max: () => MetadataReducer<number | undefined, number | undefined>;
129
+ /** Creates a reducer that logically or's its accumulated value with each individual item value. */
130
+ readonly or: () => MetadataReducer<boolean, boolean>;
131
+ /** Creates a reducer that logically and's its accumulated value with each individual item value. */
132
+ readonly and: () => MetadataReducer<boolean, boolean>;
133
+ /** Creates a reducer that always takes the next individual item value as the accumulated value. */
134
+ readonly override: typeof override;
135
+ };
136
+ declare function override<T>(): MetadataReducer<T | undefined, T>;
137
+ declare function override<T>(getInitial: () => T): MetadataReducer<T, T>;
112
138
  /**
113
139
  * Represents metadata that is aggregated from multiple parts according to the key's reducer
114
140
  * function. A value can be contributed to the aggregated value for a field using an
115
- * `aggregateMetadata` rule in the schema. There may be multiple rules in a schema that contribute
116
- * values to the same `AggregateMetadataKey` of the same field.
141
+ * `metadata` rule in the schema. There may be multiple rules in a schema that contribute
142
+ * values to the same `MetadataKey` of the same field.
143
+ *
144
+ * @template TRead The type read from the `FieldState` for this key
145
+ * @template TWrite The type written to this key using the `metadata()` rule
146
+ * @template TAcc The type of the reducer's accumulated value.
117
147
  *
118
148
  * @experimental 21.0.0
119
149
  */
120
- declare class AggregateMetadataKey<TAcc, TItem> {
121
- readonly reduce: (acc: TAcc, item: TItem) => TAcc;
122
- readonly getInitial: () => TAcc;
150
+ declare class MetadataKey<TRead, TWrite, TAcc> {
151
+ readonly reducer: MetadataReducer<TAcc, TWrite>;
152
+ readonly create: ((s: Signal<TAcc>) => TRead) | undefined;
123
153
  private brand;
124
154
  /** Use {@link reducedMetadataKey}. */
125
- private constructor();
155
+ protected constructor(reducer: MetadataReducer<TAcc, TWrite>, create: ((s: Signal<TAcc>) => TRead) | undefined);
126
156
  }
127
157
  /**
128
- * Creates an {@link AggregateMetadataKey} that reduces its individual values into an accumulated
129
- * value using the given `reduce` and `getInitial` functions.
130
- * @param reduce The reducer function.
131
- * @param getInitial A function that gets the initial value for the reduce operation.
158
+ * Extracts the the type that can be set into the given metadata key type using the `metadata()` rule.
132
159
  *
133
- * @experimental 21.0.0
134
- */
135
- declare function reducedMetadataKey<TAcc, TItem>(reduce: (acc: TAcc, item: TItem) => TAcc, getInitial: NoInfer<() => TAcc>): AggregateMetadataKey<TAcc, TItem>;
136
- /**
137
- * Creates an {@link AggregateMetadataKey} that reduces its individual values into a list.
160
+ * @template TKey The `MetadataKey` type
138
161
  *
139
162
  * @experimental 21.0.0
140
163
  */
141
- declare function listMetadataKey<TItem>(): AggregateMetadataKey<TItem[], TItem | undefined>;
164
+ type MetadataSetterType<TKey> = TKey extends MetadataKey<any, infer TWrite, any> ? TWrite : never;
142
165
  /**
143
- * Creates {@link AggregateMetadataKey} that reduces its individual values by taking their min.
166
+ * Creates a metadata key used to contain a computed value.
167
+ * The last value set on a given field tree node overrides any previously set values.
168
+ *
169
+ * @template TWrite The type written to this key using the `metadata()` rule
144
170
  *
145
171
  * @experimental 21.0.0
146
172
  */
147
- declare function minMetadataKey(): AggregateMetadataKey<number | undefined, number | undefined>;
173
+ declare function createMetadataKey<TWrite>(): MetadataKey<Signal<TWrite | undefined>, TWrite, TWrite | undefined>;
148
174
  /**
149
- * Creates {@link AggregateMetadataKey} that reduces its individual values by taking their max.
175
+ * Creates a metadata key used to contain a computed value.
176
+ *
177
+ * @param reducer The reducer used to combine individually set values into the final computed value.
178
+ * @template TWrite The type written to this key using the `metadata()` rule
179
+ * @template TAcc The type of the reducer's accumulated value.
150
180
  *
151
181
  * @experimental 21.0.0
152
182
  */
153
- declare function maxMetadataKey(): AggregateMetadataKey<number | undefined, number | undefined>;
183
+ declare function createMetadataKey<TWrite, TAcc>(reducer: MetadataReducer<TAcc, TWrite>): MetadataKey<Signal<TAcc>, TWrite, TAcc>;
154
184
  /**
155
- * Creates an {@link AggregateMetadataKey} that reduces its individual values by logically or-ing
156
- * them.
185
+ * Creates a metadata key that exposes a managed value based on the accumulated result of the values
186
+ * written to the key. The accumulated value takes the last value set on a given field tree node,
187
+ * overriding any previously set values.
188
+ *
189
+ * @param create A function that receives a signal of the accumulated value and returns the managed
190
+ * value based on it. This function runs during the construction of the `FieldTree` node,
191
+ * and runs in the injection context of that node.
192
+ * @template TRead The type read from the `FieldState` for this key
193
+ * @template TWrite The type written to this key using the `metadata()` rule
157
194
  *
158
195
  * @experimental 21.0.0
159
196
  */
160
- declare function orMetadataKey(): AggregateMetadataKey<boolean, boolean>;
197
+ declare function createManagedMetadataKey<TRead, TWrite>(create: (s: Signal<TWrite | undefined>) => TRead): MetadataKey<TRead, TWrite, TWrite | undefined>;
161
198
  /**
162
- * Creates an {@link AggregateMetadataKey} that reduces its individual values by logically and-ing
163
- * them.
199
+ * Creates a metadata key that exposes a managed value based on the accumulated result of the values
200
+ * written to the key.
201
+ *
202
+ * @param create A function that receives a signal of the accumulated value and returns the managed
203
+ * value based on it. This function runs during the construction of the `FieldTree` node,
204
+ * and runs in the injection context of that node.
205
+ * @param reducer The reducer used to combine individual value written to the key,
206
+ * this will determine the accumulated value that the create function receives.
207
+ * @template TRead The type read from the `FieldState` for this key
208
+ * @template TWrite The type written to this key using the `metadata()` rule
209
+ * @template TAcc The type of the reducer's accumulated value.
164
210
  *
165
211
  * @experimental 21.0.0
166
212
  */
167
- declare function andMetadataKey(): AggregateMetadataKey<boolean, boolean>;
213
+ declare function createManagedMetadataKey<TRead, TWrite, TAcc>(create: (s: Signal<TAcc>) => TRead, reducer: MetadataReducer<TAcc, TWrite>): MetadataKey<TRead, TWrite, TAcc>;
168
214
  /**
169
- * An {@link AggregateMetadataKey} representing whether the field is required.
215
+ * A {@link MetadataKey} representing whether the field is required.
170
216
  *
171
217
  * @category validation
172
218
  * @experimental 21.0.0
173
219
  */
174
- declare const REQUIRED: AggregateMetadataKey<boolean, boolean>;
220
+ declare const REQUIRED: MetadataKey<Signal<boolean>, boolean, boolean>;
175
221
  /**
176
- * An {@link AggregateMetadataKey} representing the min value of the field.
222
+ * A {@link MetadataKey} representing the min value of the field.
177
223
  *
178
224
  * @category validation
179
225
  * @experimental 21.0.0
180
226
  */
181
- declare const MIN: AggregateMetadataKey<number | undefined, number | undefined>;
227
+ declare const MIN: MetadataKey<Signal<number | undefined>, number | undefined, number | undefined>;
182
228
  /**
183
- * An {@link AggregateMetadataKey} representing the max value of the field.
229
+ * A {@link MetadataKey} representing the max value of the field.
184
230
  *
185
231
  * @category validation
186
232
  * @experimental 21.0.0
187
233
  */
188
- declare const MAX: AggregateMetadataKey<number | undefined, number | undefined>;
234
+ declare const MAX: MetadataKey<Signal<number | undefined>, number | undefined, number | undefined>;
189
235
  /**
190
- * An {@link AggregateMetadataKey} representing the min length of the field.
236
+ * A {@link MetadataKey} representing the min length of the field.
191
237
  *
192
238
  * @category validation
193
239
  * @experimental 21.0.0
194
240
  */
195
- declare const MIN_LENGTH: AggregateMetadataKey<number | undefined, number | undefined>;
241
+ declare const MIN_LENGTH: MetadataKey<Signal<number | undefined>, number | undefined, number | undefined>;
196
242
  /**
197
- * An {@link AggregateMetadataKey} representing the max length of the field.
243
+ * A {@link MetadataKey} representing the max length of the field.
198
244
  *
199
245
  * @category validation
200
246
  * @experimental 21.0.0
201
247
  */
202
- declare const MAX_LENGTH: AggregateMetadataKey<number | undefined, number | undefined>;
248
+ declare const MAX_LENGTH: MetadataKey<Signal<number | undefined>, number | undefined, number | undefined>;
203
249
  /**
204
- * An {@link AggregateMetadataKey} representing the patterns the field must match.
250
+ * A {@link MetadataKey} representing the patterns the field must match.
205
251
  *
206
252
  * @category validation
207
253
  * @experimental 21.0.0
208
254
  */
209
- declare const PATTERN: AggregateMetadataKey<RegExp[], RegExp | undefined>;
255
+ declare const PATTERN: MetadataKey<Signal<RegExp[]>, RegExp | undefined, RegExp[]>;
210
256
 
211
257
  /**
212
- * Options used to create a `ValidationError`.
258
+ * Symbol used to retain generic type information when it would otherwise be lost.
213
259
  */
214
- interface ValidationErrorOptions {
215
- /** Human readable error message. */
216
- message?: string;
217
- }
260
+ declare const ɵɵTYPE: unique symbol;
218
261
  /**
219
- * A type that requires the given type `T` to have a `field` property.
220
- * @template T The type to add a `field` to.
262
+ * A type that represents either a single value of type `T` or a readonly array of `T`.
263
+ * @template T The type of the value(s).
221
264
  *
222
265
  * @experimental 21.0.0
223
266
  */
224
- type WithField<T> = T & {
225
- field: FieldTree<unknown>;
226
- };
267
+ type OneOrMany<T> = T | readonly T[];
227
268
  /**
228
- * A type that allows the given type `T` to optionally have a `field` property.
229
- * @template T The type to optionally add a `field` to.
269
+ * The kind of `FieldPath` (`Root`, `Child` of another `FieldPath`, or `Item` in a `FieldPath` array)
230
270
  *
231
271
  * @experimental 21.0.0
232
272
  */
233
- type WithOptionalField<T> = Omit<T, 'field'> & {
234
- field?: FieldTree<unknown>;
235
- };
273
+ type PathKind = PathKind.Root | PathKind.Child | PathKind.Item;
274
+ declare namespace PathKind {
275
+ /**
276
+ * The `PathKind` for a `FieldPath` that is at the root of its field tree.
277
+ */
278
+ interface Root {
279
+ /**
280
+ * The `ɵɵTYPE` is constructed to allow the `extends` clause on `Child` and `Item` to narrow the
281
+ * type. Another way to think about this is, if we have a function that expects this kind of
282
+ * path, the `ɵɵTYPE` lists the kinds of path we are allowed to pass to it.
283
+ */
284
+ [ɵɵTYPE]: 'root' | 'child' | 'item';
285
+ }
286
+ /**
287
+ * The `PathKind` for a `FieldPath` that is a child of another `FieldPath`.
288
+ */
289
+ interface Child extends PathKind.Root {
290
+ [ɵɵTYPE]: 'child' | 'item';
291
+ }
292
+ /**
293
+ * The `PathKind` for a `FieldPath` that is an item in a `FieldPath` array.
294
+ */
295
+ interface Item extends PathKind.Child {
296
+ [ɵɵTYPE]: 'item';
297
+ }
298
+ }
236
299
  /**
237
- * A type that ensures the given type `T` does not have a `field` property.
238
- * @template T The type to remove the `field` from.
300
+ * A status indicating whether a field is unsubmitted, submitted, or currently submitting.
239
301
  *
302
+ * @category types
240
303
  * @experimental 21.0.0
241
304
  */
242
- type WithoutField<T> = T & {
243
- field: never;
244
- };
305
+ type SubmittedStatus = 'unsubmitted' | 'submitted' | 'submitting';
245
306
  /**
246
- * Create a required error associated with the target field
247
- * @param options The validation error options
307
+ * A reason for a field's disablement.
248
308
  *
309
+ * @category logic
249
310
  * @experimental 21.0.0
250
311
  */
251
- declare function requiredError(options: WithField<ValidationErrorOptions>): RequiredValidationError;
312
+ interface DisabledReason {
313
+ /** The field that is disabled. */
314
+ readonly field: FieldTree<unknown>;
315
+ /** A user-facing message describing the reason for the disablement. */
316
+ readonly message?: string;
317
+ }
252
318
  /**
253
- * Create a required error
254
- * @param options The optional validation error options
319
+ * The absence of an error which indicates a successful validation result.
255
320
  *
256
- * @category validation
321
+ * @category types
257
322
  * @experimental 21.0.0
258
323
  */
259
- declare function requiredError(options?: ValidationErrorOptions): WithoutField<RequiredValidationError>;
324
+ type ValidationSuccess = null | undefined | void;
260
325
  /**
261
- * Create a min value error associated with the target field
262
- * @param min The min value constraint
263
- * @param options The validation error options
326
+ * The result of running a tree validation function.
264
327
  *
265
- * @category validation
266
- * @experimental 21.0.0
267
- */
268
- declare function minError(min: number, options: WithField<ValidationErrorOptions>): MinValidationError;
269
- /**
270
- * Create a min value error
271
- * @param min The min value constraint
272
- * @param options The optional validation error options
328
+ * The result may be one of the following:
329
+ * 1. A {@link ValidationSuccess} to indicate no errors.
330
+ * 2. A {@link ValidationError} without a field to indicate an error on the field being validated.
331
+ * 3. A {@link ValidationError} with a field to indicate an error on the target field.
332
+ * 4. A list of {@link ValidationError} with or without fields to indicate multiple errors.
273
333
  *
274
- * @category validation
275
- * @experimental 21.0.0
276
- */
277
- declare function minError(min: number, options?: ValidationErrorOptions): WithoutField<MinValidationError>;
278
- /**
279
- * Create a max value error associated with the target field
280
- * @param max The max value constraint
281
- * @param options The validation error options
334
+ * @template E the type of error (defaults to {@link ValidationError}).
282
335
  *
283
- * @category validation
336
+ * @category types
284
337
  * @experimental 21.0.0
285
338
  */
286
- declare function maxError(max: number, options: WithField<ValidationErrorOptions>): MaxValidationError;
339
+ type TreeValidationResult<E extends ValidationError.WithOptionalField = ValidationError.WithOptionalField> = ValidationSuccess | OneOrMany<E>;
287
340
  /**
288
- * Create a max value error
289
- * @param max The max value constraint
290
- * @param options The optional validation error options
341
+ * A validation result where all errors explicitly define their target field.
291
342
  *
292
- * @category validation
293
- * @experimental 21.0.0
294
- */
295
- declare function maxError(max: number, options?: ValidationErrorOptions): WithoutField<MaxValidationError>;
296
- /**
297
- * Create a minLength error associated with the target field
298
- * @param minLength The minLength constraint
299
- * @param options The validation error options
343
+ * The result may be one of the following:
344
+ * 1. A {@link ValidationSuccess} to indicate no errors.
345
+ * 2. A {@link ValidationError} with a field to indicate an error on the target field.
346
+ * 3. A list of {@link ValidationError} with fields to indicate multiple errors.
300
347
  *
301
- * @category validation
302
- * @experimental 21.0.0
303
- */
304
- declare function minLengthError(minLength: number, options: WithField<ValidationErrorOptions>): MinLengthValidationError;
305
- /**
306
- * Create a minLength error
307
- * @param minLength The minLength constraint
308
- * @param options The optional validation error options
348
+ * @template E the type of error (defaults to {@link ValidationError}).
309
349
  *
310
- * @category validation
350
+ * @category types
311
351
  * @experimental 21.0.0
312
352
  */
313
- declare function minLengthError(minLength: number, options?: ValidationErrorOptions): WithoutField<MinLengthValidationError>;
353
+ type ValidationResult<E extends ValidationError = ValidationError> = ValidationSuccess | OneOrMany<E>;
314
354
  /**
315
- * Create a maxLength error associated with the target field
316
- * @param maxLength The maxLength constraint
317
- * @param options The validation error options
355
+ * An asynchronous validation result where all errors explicitly define their target field.
318
356
  *
319
- * @category validation
320
- * @experimental 21.0.0
321
- */
322
- declare function maxLengthError(maxLength: number, options: WithField<ValidationErrorOptions>): MaxLengthValidationError;
323
- /**
324
- * Create a maxLength error
325
- * @param maxLength The maxLength constraint
326
- * @param options The optional validation error options
357
+ * The result may be one of the following:
358
+ * 1. A {@link ValidationResult} to indicate the result if resolved.
359
+ * 5. 'pending' if the validation is not yet resolved.
327
360
  *
328
- * @category validation
329
- * @experimental 21.0.0
330
- */
331
- declare function maxLengthError(maxLength: number, options?: ValidationErrorOptions): WithoutField<MaxLengthValidationError>;
332
- /**
333
- * Create a pattern matching error associated with the target field
334
- * @param pattern The violated pattern
335
- * @param options The validation error options
361
+ * @template E the type of error (defaults to {@link ValidationError}).
336
362
  *
337
- * @category validation
363
+ * @category types
338
364
  * @experimental 21.0.0
339
365
  */
340
- declare function patternError(pattern: RegExp, options: WithField<ValidationErrorOptions>): PatternValidationError;
366
+ type AsyncValidationResult<E extends ValidationError = ValidationError> = ValidationResult<E> | 'pending';
341
367
  /**
342
- * Create a pattern matching error
343
- * @param pattern The violated pattern
344
- * @param options The optional validation error options
368
+ * An object that represents a tree of fields in a form. This includes both primitive value fields
369
+ * (e.g. fields that contain a `string` or `number`), as well as "grouping fields" that contain
370
+ * sub-fields. `FieldTree` objects are arranged in a tree whose structure mimics the structure of the
371
+ * underlying data. For example a `FieldTree<{x: number}>` has a property `x` which contains a
372
+ * `FieldTree<number>`. To access the state associated with a field, call it as a function.
345
373
  *
346
- * @category validation
347
- * @experimental 21.0.0
348
- */
349
- declare function patternError(pattern: RegExp, options?: ValidationErrorOptions): WithoutField<PatternValidationError>;
350
- /**
351
- * Create an email format error associated with the target field
352
- * @param options The validation error options
374
+ * @template TValue The type of the data which the field is wrapped around.
375
+ * @template TKey The type of the property key which this field resides under in its parent.
353
376
  *
354
- * @category validation
377
+ * @category types
355
378
  * @experimental 21.0.0
356
379
  */
357
- declare function emailError(options: WithField<ValidationErrorOptions>): EmailValidationError;
380
+ type FieldTree<TModel, TKey extends string | number = string | number> = (() => [TModel] extends [AbstractControl] ? CompatFieldState<TModel, TKey> : FieldState<TModel, TKey>) & ([TModel] extends [AbstractControl] ? object : [TModel] extends [Array<infer U>] ? ReadonlyArrayLike<MaybeFieldTree<U, number>> : TModel extends Record<string, any> ? Subfields<TModel> : object);
358
381
  /**
359
- * Create an email format error
360
- * @param options The optional validation error options
382
+ * The sub-fields that a user can navigate to from a `FieldTree<TModel>`.
361
383
  *
362
- * @category validation
363
- * @experimental 21.0.0
364
- */
365
- declare function emailError(options?: ValidationErrorOptions): WithoutField<EmailValidationError>;
366
- /**
367
- * Create a standard schema issue error associated with the target field
368
- * @param issue The standard schema issue
369
- * @param options The validation error options
384
+ * @template TModel The type of the data which the parent field is wrapped around.
370
385
  *
371
- * @category validation
372
386
  * @experimental 21.0.0
373
387
  */
374
- declare function standardSchemaError(issue: StandardSchemaV1.Issue, options: WithField<ValidationErrorOptions>): StandardSchemaValidationError;
388
+ type Subfields<TModel> = {
389
+ readonly [K in keyof TModel as TModel[K] extends Function ? never : K]: MaybeFieldTree<TModel[K], string>;
390
+ } & {
391
+ [Symbol.iterator](): Iterator<[string, MaybeFieldTree<TModel[keyof TModel], string>]>;
392
+ };
375
393
  /**
376
- * Create a standard schema issue error
377
- * @param issue The standard schema issue
378
- * @param options The optional validation error options
394
+ * An iterable object with the same shape as a readonly array.
379
395
  *
380
- * @category validation
381
- * @experimental 21.0.0
382
- */
383
- declare function standardSchemaError(issue: StandardSchemaV1.Issue, options?: ValidationErrorOptions): WithoutField<StandardSchemaValidationError>;
384
- /**
385
- * Create a custom error associated with the target field
386
- * @param obj The object to create an error from
396
+ * @template T The array item type.
387
397
  *
388
- * @category validation
389
398
  * @experimental 21.0.0
390
399
  */
391
- declare function customError<E extends Partial<ValidationError.WithField>>(obj: WithField<E>): CustomValidationError;
400
+ type ReadonlyArrayLike<T> = Pick<ReadonlyArray<T>, number | 'length' | typeof Symbol.iterator>;
392
401
  /**
393
- * Create a custom error
394
- * @param obj The object to create an error from
402
+ * Helper type for defining `FieldTree`. Given a type `TValue` that may include `undefined`, it extracts
403
+ * the `undefined` outside the `FieldTree` type.
404
+ *
405
+ * For example `MaybeField<{a: number} | undefined, TKey>` would be equivalent to
406
+ * `undefined | FieldTree<{a: number}, TKey>`.
407
+ *
408
+ * @template TModel The type of the data which the field is wrapped around.
409
+ * @template TKey The type of the property key which this field resides under in its parent.
395
410
  *
396
- * @category validation
397
411
  * @experimental 21.0.0
398
412
  */
399
- declare function customError<E extends Partial<ValidationError.WithField>>(obj?: E): WithoutField<CustomValidationError>;
413
+ type MaybeFieldTree<TModel, TKey extends string | number = string | number> = (TModel & undefined) | FieldTree<Exclude<TModel, undefined>, TKey>;
400
414
  /**
401
- * Common interface for all validation errors.
402
- *
403
- * This can be returned from validators.
404
- *
405
- * It's also used by the creation functions to create an instance
406
- * (e.g. `requiredError`, `minError`, etc.).
415
+ * Contains all of the state (e.g. value, statuses, etc.) associated with a `FieldTree`, exposed as
416
+ * signals.
407
417
  *
408
- * @category validation
418
+ * @category structure
409
419
  * @experimental 21.0.0
410
420
  */
411
- interface ValidationError {
412
- /** Identifies the kind of error. */
413
- readonly kind: string;
414
- /** Human readable error message. */
415
- readonly message?: string;
416
- }
417
- declare namespace ValidationError {
421
+ interface FieldState<TValue, TKey extends string | number = string | number> extends _FieldState<TValue> {
418
422
  /**
419
- * Validation error with a field.
423
+ * A signal indicating whether field value has been changed by user.
424
+ */
425
+ readonly dirty: Signal<boolean>;
426
+ /**
427
+ * A signal indicating whether a field is hidden.
420
428
  *
421
- * This is returned from field state, e.g., catField.errors() would be of a list of errors with
422
- * `field: catField` bound to state.
429
+ * When a field is hidden it is ignored when determining the valid, touched, and dirty states.
430
+ *
431
+ * Note: This doesn't hide the field in the template, that must be done manually.
432
+ * ```
433
+ * @if (!field.hidden()) {
434
+ * ...
435
+ * }
436
+ * ```
423
437
  */
424
- interface WithField extends ValidationError {
425
- /** The field associated with this error. */
426
- readonly field: FieldTree<unknown>;
427
- }
438
+ readonly hidden: Signal<boolean>;
439
+ readonly disabledReasons: Signal<readonly DisabledReason[]>;
440
+ readonly errors: Signal<ValidationError.WithField[]>;
428
441
  /**
429
- * Validation error with optional field.
442
+ * A signal containing the {@link errors} of the field and its descendants.
443
+ */
444
+ readonly errorSummary: Signal<ValidationError.WithField[]>;
445
+ /**
446
+ * A signal indicating whether the field's value is currently valid.
430
447
  *
431
- * This is generally used in places where the result might have a field.
432
- * e.g., as a result of a `validateTree`, or when handling form submission.
448
+ * Note: `valid()` is not the same as `!invalid()`.
449
+ * - `valid()` is `true` when there are no validation errors *and* no pending validators.
450
+ * - `invalid()` is `true` when there are validation errors, regardless of pending validators.
451
+ *
452
+ * Ex: consider the situation where a field has 3 validators, 2 of which have no errors and 1 of
453
+ * which is still pending. In this case `valid()` is `false` because of the pending validator.
454
+ * However `invalid()` is also `false` because there are no errors.
433
455
  */
434
- interface WithOptionalField extends ValidationError {
435
- /** The field associated with this error. */
436
- readonly field?: FieldTree<unknown>;
437
- }
456
+ readonly valid: Signal<boolean>;
438
457
  /**
439
- * Validation error with no field.
458
+ * A signal indicating whether the field's value is currently invalid.
440
459
  *
441
- * This is used to strongly enforce that fields are not allowed in validation result.
460
+ * Note: `invalid()` is not the same as `!valid()`.
461
+ * - `invalid()` is `true` when there are validation errors, regardless of pending validators.
462
+ * - `valid()` is `true` when there are no validation errors *and* no pending validators.
463
+ *
464
+ * Ex: consider the situation where a field has 3 validators, 2 of which have no errors and 1 of
465
+ * which is still pending. In this case `invalid()` is `false` because there are no errors.
466
+ * However `valid()` is also `false` because of the pending validator.
442
467
  */
443
- interface WithoutField extends ValidationError {
444
- /** The field associated with this error. */
445
- readonly field?: never;
446
- }
468
+ readonly invalid: Signal<boolean>;
469
+ /**
470
+ * Whether there are any validators still pending for this field.
471
+ */
472
+ readonly pending: Signal<boolean>;
473
+ /**
474
+ * A signal indicating whether the field is currently in the process of being submitted.
475
+ */
476
+ readonly submitting: Signal<boolean>;
477
+ /**
478
+ * The property key in the parent field under which this field is stored. If the parent field is
479
+ * array-valued, for example, this is the index of this field in that array.
480
+ */
481
+ readonly keyInParent: Signal<TKey>;
482
+ /**
483
+ * The {@link Field} directives that bind this field to a UI control.
484
+ */
485
+ readonly fieldBindings: Signal<readonly Field<unknown>[]>;
486
+ /**
487
+ * Reads a metadata value from the field.
488
+ * @param key The metadata key to read.
489
+ */
490
+ metadata<M>(key: MetadataKey<M, any, any>): M | undefined;
491
+ /**
492
+ * Resets the {@link touched} and {@link dirty} state of the field and its descendants.
493
+ *
494
+ * Note this does not change the data model, which can be reset directly if desired.
495
+ *
496
+ * @param value Optional value to set to the form. If not passed, the value will not be changed.
497
+ */
498
+ reset(value?: TValue): void;
447
499
  }
448
500
  /**
449
- * A custom error that may contain additional properties
501
+ * This is FieldState also providing access to the wrapped FormControl.
450
502
  *
451
- * @category validation
503
+ * @category interop
452
504
  * @experimental 21.0.0
453
505
  */
454
- declare class CustomValidationError implements ValidationError {
455
- /** Brand the class to avoid Typescript structural matching */
456
- private __brand;
506
+ type CompatFieldState<TControl extends AbstractControl, TKey extends string | number = string | number> = FieldState<TControl extends AbstractControl<unknown, infer TValue> ? TValue : never, TKey> & {
507
+ control: Signal<TControl>;
508
+ };
509
+ /**
510
+ * Allows declaring whether the Rules are supported for a given path.
511
+ *
512
+ * @experimental 21.0.0
513
+ **/
514
+ type SchemaPathRules = SchemaPathRules.Supported | SchemaPathRules.Unsupported;
515
+ declare namespace SchemaPathRules {
457
516
  /**
458
- * Allow the user to attach arbitrary other properties.
517
+ * Used for paths that support settings rules.
459
518
  */
460
- [key: PropertyKey]: unknown;
461
- /** Identifies the kind of error. */
462
- readonly kind: string;
463
- /** The field associated with this error. */
464
- readonly field: FieldTree<unknown>;
465
- /** Human readable error message. */
466
- readonly message?: string;
467
- constructor(options?: ValidationErrorOptions);
519
+ type Supported = 1;
520
+ /**
521
+ * Used for paths that do not support settings rules, e.g., compatPath.
522
+ */
523
+ type Unsupported = 2;
468
524
  }
469
525
  /**
470
- * Internal version of `NgValidationError`, we create this separately so we can change its type on
471
- * the exported version to a type union of the possible sub-classes.
526
+ * An object that represents a location in the `FieldTree` tree structure and is used to bind logic to a
527
+ * particular part of the structure prior to the creation of the form. Because the `FieldPath`
528
+ * exists prior to the form's creation, it cannot be used to access any of the field state.
472
529
  *
530
+ * @template TValue The type of the data which the form is wrapped around.
531
+ * @template TPathKind The kind of path (root field, child field, or item of an array)
532
+ *
533
+ * @category types
473
534
  * @experimental 21.0.0
474
535
  */
475
- declare abstract class _NgValidationError implements ValidationError {
476
- /** Brand the class to avoid Typescript structural matching */
477
- private __brand;
478
- /** Identifies the kind of error. */
479
- readonly kind: string;
480
- /** The field associated with this error. */
481
- readonly field: FieldTree<unknown>;
482
- /** Human readable error message. */
483
- readonly message?: string;
484
- constructor(options?: ValidationErrorOptions);
485
- }
536
+ type SchemaPath<TValue, TSupportsRules extends SchemaPathRules = SchemaPathRules.Supported, TPathKind extends PathKind = PathKind.Root> = {
537
+ [ɵɵTYPE]: {
538
+ value: () => TValue;
539
+ supportsRules: TSupportsRules;
540
+ pathKind: TPathKind;
541
+ };
542
+ };
486
543
  /**
487
- * An error used to indicate that a required field is empty.
544
+ * Schema path used if the value is an AbstractControl.
488
545
  *
489
- * @category validation
546
+ * @category interop
490
547
  * @experimental 21.0.0
491
548
  */
492
- declare class RequiredValidationError extends _NgValidationError {
493
- readonly kind = "required";
494
- }
549
+ type CompatSchemaPath<TControl extends AbstractControl, TPathKind extends PathKind = PathKind.Root> = SchemaPath<TControl extends AbstractControl<unknown, infer TValue> ? TValue : never, SchemaPathRules.Unsupported, TPathKind> & {
550
+ [ɵɵTYPE]: {
551
+ control: TControl;
552
+ };
553
+ };
495
554
  /**
496
- * An error used to indicate that a value is lower than the minimum allowed.
555
+ * Nested schema path.
556
+ *
557
+ * It mirrors the structure of a given data structure, and allows applying rules to the appropriate
558
+ * fields.
497
559
  *
498
- * @category validation
499
560
  * @experimental 21.0.0
500
561
  */
501
- declare class MinValidationError extends _NgValidationError {
502
- readonly min: number;
503
- readonly kind = "min";
504
- constructor(min: number, options?: ValidationErrorOptions);
505
- }
562
+ type SchemaPathTree<TModel, TPathKind extends PathKind = PathKind.Root> = ([TModel] extends [AbstractControl] ? CompatSchemaPath<TModel, TPathKind> : SchemaPath<TModel, SchemaPathRules.Supported, TPathKind>) & (TModel extends AbstractControl ? unknown : TModel extends Array<any> ? unknown : TModel extends Record<string, any> ? {
563
+ [K in keyof TModel]: MaybeSchemaPathTree<TModel[K], PathKind.Child>;
564
+ } : unknown);
506
565
  /**
507
- * An error used to indicate that a value is higher than the maximum allowed.
566
+ * Helper type for defining `FieldPath`. Given a type `TValue` that may include `undefined`, it
567
+ * extracts the `undefined` outside the `FieldPath` type.
568
+ *
569
+ * For example `MaybeFieldPath<{a: number} | undefined, PathKind.Child>` would be equivalent to
570
+ * `undefined | FieldTree<{a: number}, PathKind.child>`.
571
+ *
572
+ * @template TValue The type of the data which the field is wrapped around.
573
+ * @template TPathKind The kind of path (root field, child field, or item of an array)
508
574
  *
509
- * @category validation
510
575
  * @experimental 21.0.0
511
576
  */
512
- declare class MaxValidationError extends _NgValidationError {
513
- readonly max: number;
514
- readonly kind = "max";
515
- constructor(max: number, options?: ValidationErrorOptions);
516
- }
577
+ type MaybeSchemaPathTree<TModel, TPathKind extends PathKind = PathKind.Root> = (TModel & undefined) | SchemaPathTree<Exclude<TModel, undefined>, TPathKind>;
517
578
  /**
518
- * An error used to indicate that a value is shorter than the minimum allowed length.
579
+ * Defines logic for a form.
519
580
  *
520
- * @category validation
581
+ * @template TValue The type of data stored in the form that this schema is attached to.
582
+ *
583
+ * @category types
521
584
  * @experimental 21.0.0
522
585
  */
523
- declare class MinLengthValidationError extends _NgValidationError {
524
- readonly minLength: number;
525
- readonly kind = "minLength";
526
- constructor(minLength: number, options?: ValidationErrorOptions);
527
- }
586
+ type Schema<in TModel> = {
587
+ [ɵɵTYPE]: SchemaFn<TModel, PathKind.Root>;
588
+ };
528
589
  /**
529
- * An error used to indicate that a value is longer than the maximum allowed length.
590
+ * Function that defines rules for a schema.
530
591
  *
531
- * @category validation
592
+ * @template TModel The type of data stored in the form that this schema function is attached to.
593
+ * @template TPathKind The kind of path this schema function can be bound to.
594
+ *
595
+ * @category types
532
596
  * @experimental 21.0.0
533
597
  */
534
- declare class MaxLengthValidationError extends _NgValidationError {
535
- readonly maxLength: number;
536
- readonly kind = "maxLength";
537
- constructor(maxLength: number, options?: ValidationErrorOptions);
538
- }
598
+ type SchemaFn<TModel, TPathKind extends PathKind = PathKind.Root> = (p: SchemaPathTree<TModel, TPathKind>) => void;
539
599
  /**
540
- * An error used to indicate that a value does not match the required pattern.
600
+ * A schema or schema definition function.
541
601
  *
542
- * @category validation
602
+ * @template TModel The type of data stored in the form that this schema function is attached to.
603
+ * @template TPathKind The kind of path this schema function can be bound to.
604
+ *
605
+ * @category types
543
606
  * @experimental 21.0.0
544
607
  */
545
- declare class PatternValidationError extends _NgValidationError {
546
- readonly pattern: RegExp;
547
- readonly kind = "pattern";
548
- constructor(pattern: RegExp, options?: ValidationErrorOptions);
549
- }
608
+ type SchemaOrSchemaFn<TModel, TPathKind extends PathKind = PathKind.Root> = Schema<TModel> | SchemaFn<TModel, TPathKind>;
550
609
  /**
551
- * An error used to indicate that a value is not a valid email.
610
+ * A function that receives the `FieldContext` for the field the logic is bound to and returns
611
+ * a specific result type.
552
612
  *
553
- * @category validation
613
+ * @template TValue The data type for the field the logic is bound to.
614
+ * @template TReturn The type of the result returned by the logic function.
615
+ * @template TPathKind The kind of path the logic is applied to (root field, child field, or item of an array)
616
+ *
617
+ * @category types
554
618
  * @experimental 21.0.0
555
619
  */
556
- declare class EmailValidationError extends _NgValidationError {
557
- readonly kind = "email";
558
- }
620
+ type LogicFn<TValue, TReturn, TPathKind extends PathKind = PathKind.Root> = (ctx: FieldContext<TValue, TPathKind>) => TReturn;
559
621
  /**
560
- * An error used to indicate an issue validating against a standard schema.
622
+ * A function that takes the `FieldContext` for the field being validated and returns a
623
+ * `ValidationResult` indicating errors for the field.
624
+ *
625
+ * @template TValue The type of value stored in the field being validated
626
+ * @template TPathKind The kind of path being validated (root field, child field, or item of an array)
561
627
  *
562
628
  * @category validation
563
629
  * @experimental 21.0.0
564
630
  */
565
- declare class StandardSchemaValidationError extends _NgValidationError {
566
- readonly issue: StandardSchemaV1.Issue;
567
- readonly kind = "standardSchema";
568
- constructor(issue: StandardSchemaV1.Issue, options?: ValidationErrorOptions);
569
- }
631
+ type FieldValidator<TValue, TPathKind extends PathKind = PathKind.Root> = LogicFn<TValue, ValidationResult<ValidationError.WithoutField>, TPathKind>;
570
632
  /**
571
- * The base class for all built-in, non-custom errors. This class can be used to check if an error
572
- * is one of the standard kinds, allowing you to switch on the kind to further narrow the type.
633
+ * A function that takes the `FieldContext` for the field being validated and returns a
634
+ * `TreeValidationResult` indicating errors for the field and its sub-fields.
573
635
  *
574
- * @example
575
- * ```ts
576
- * const f = form(...);
577
- * for (const e of form().errors()) {
578
- * if (e instanceof NgValidationError) {
579
- * switch(e.kind) {
580
- * case 'required':
581
- * console.log('This is required!');
582
- * break;
583
- * case 'min':
584
- * console.log(`Must be at least ${e.min}`);
585
- * break;
586
- * ...
587
- * }
588
- * }
589
- * }
590
- * ```
636
+ * @template TValue The type of value stored in the field being validated
637
+ * @template TPathKind The kind of path being validated (root field, child field, or item of an array)
591
638
  *
592
- * @category validation
639
+ * @category types
593
640
  * @experimental 21.0.0
594
641
  */
595
- declare const NgValidationError: abstract new () => NgValidationError;
596
- type NgValidationError = RequiredValidationError | MinValidationError | MaxValidationError | MinLengthValidationError | MaxLengthValidationError | PatternValidationError | EmailValidationError | StandardSchemaValidationError;
597
-
642
+ type TreeValidator<TValue, TPathKind extends PathKind = PathKind.Root> = LogicFn<TValue, TreeValidationResult, TPathKind>;
598
643
  /**
599
- * Symbol used to retain generic type information when it would otherwise be lost.
644
+ * A function that takes the `FieldContext` for the field being validated and returns a
645
+ * `ValidationResult` indicating errors for the field and its sub-fields. In a `Validator` all
646
+ * errors must explicitly define their target field.
647
+ *
648
+ * @template TValue The type of value stored in the field being validated
649
+ * @template TPathKind The kind of path being validated (root field, child field, or item of an array)
650
+ *
651
+ * @category types
652
+ * @experimental 21.0.0
600
653
  */
601
- declare const ɵɵTYPE: unique symbol;
654
+ type Validator<TValue, TPathKind extends PathKind = PathKind.Root> = LogicFn<TValue, ValidationResult, TPathKind>;
602
655
  /**
603
- * A type that represents either a single value of type `T` or a readonly array of `T`.
604
- * @template T The type of the value(s).
656
+ * Provides access to the state of the current field as well as functions that can be used to look
657
+ * up state of other fields based on a `FieldPath`.
605
658
  *
659
+ * @category types
606
660
  * @experimental 21.0.0
607
661
  */
608
- type OneOrMany<T> = T | readonly T[];
662
+ type FieldContext<TValue, TPathKind extends PathKind = PathKind.Root> = TPathKind extends PathKind.Item ? ItemFieldContext<TValue> : TPathKind extends PathKind.Child ? ChildFieldContext<TValue> : RootFieldContext<TValue>;
609
663
  /**
610
- * The kind of `FieldPath` (`Root`, `Child` of another `FieldPath`, or `Item` in a `FieldPath` array)
664
+ * The base field context that is available for all fields.
611
665
  *
612
666
  * @experimental 21.0.0
613
667
  */
614
- type PathKind = PathKind.Root | PathKind.Child | PathKind.Item;
615
- declare namespace PathKind {
616
- /**
617
- * The `PathKind` for a `FieldPath` that is at the root of its field tree.
618
- */
619
- interface Root {
620
- /**
621
- * The `ɵɵTYPE` is constructed to allow the `extends` clause on `Child` and `Item` to narrow the
622
- * type. Another way to think about this is, if we have a function that expects this kind of
623
- * path, the `ɵɵTYPE` lists the kinds of path we are allowed to pass to it.
624
- */
625
- [ɵɵTYPE]: 'root' | 'child' | 'item';
626
- }
627
- /**
628
- * The `PathKind` for a `FieldPath` that is a child of another `FieldPath`.
629
- */
630
- interface Child extends PathKind.Root {
631
- [ɵɵTYPE]: 'child' | 'item';
632
- }
633
- /**
634
- * The `PathKind` for a `FieldPath` that is an item in a `FieldPath` array.
635
- */
636
- interface Item extends PathKind.Child {
637
- [ɵɵTYPE]: 'item';
638
- }
668
+ interface RootFieldContext<TValue> {
669
+ /** A signal containing the value of the current field. */
670
+ readonly value: Signal<TValue>;
671
+ /** The state of the current field. */
672
+ readonly state: FieldState<TValue>;
673
+ /** The current field. */
674
+ readonly field: FieldTree<TValue>;
675
+ /** Gets the value of the field represented by the given path. */
676
+ valueOf<PValue>(p: SchemaPath<PValue, SchemaPathRules>): PValue;
677
+ /** Gets the state of the field represented by the given path. */
678
+ stateOf<PControl extends AbstractControl>(p: CompatSchemaPath<PControl>): CompatFieldState<PControl>;
679
+ stateOf<PValue>(p: SchemaPath<PValue, SchemaPathRules>): FieldState<PValue>;
680
+ /** Gets the field represented by the given path. */
681
+ fieldTreeOf<PModel>(p: SchemaPathTree<PModel>): FieldTree<PModel>;
682
+ /** The list of keys that lead from the root field to the current field. */
683
+ readonly pathKeys: Signal<readonly string[]>;
639
684
  }
640
685
  /**
641
- * A status indicating whether a field is unsubmitted, submitted, or currently submitting.
686
+ * Field context that is available for all fields that are a child of another field.
642
687
  *
643
- * @category types
688
+ * @category structure
644
689
  * @experimental 21.0.0
645
690
  */
646
- type SubmittedStatus = 'unsubmitted' | 'submitted' | 'submitting';
691
+ interface ChildFieldContext<TValue> extends RootFieldContext<TValue> {
692
+ /** The key of the current field in its parent field. */
693
+ readonly key: Signal<string>;
694
+ }
647
695
  /**
648
- * A reason for a field's disablement.
696
+ * Field context that is available for all fields that are an item in an array field.
649
697
  *
650
- * @category logic
651
698
  * @experimental 21.0.0
652
699
  */
653
- interface DisabledReason {
654
- /** The field that is disabled. */
655
- readonly field: FieldTree<unknown>;
656
- /** A user-facing message describing the reason for the disablement. */
657
- readonly message?: string;
700
+ interface ItemFieldContext<TValue> extends ChildFieldContext<TValue> {
701
+ /** The index of the current field in its parent field. */
702
+ readonly index: Signal<number>;
658
703
  }
659
704
  /**
660
- * The absence of an error which indicates a successful validation result.
705
+ * Gets the item type of an object that is possibly an array.
661
706
  *
662
- * @category types
663
707
  * @experimental 21.0.0
664
708
  */
665
- type ValidationSuccess = null | undefined | void;
709
+ type ItemType<T extends Object> = T extends ReadonlyArray<any> ? T[number] : T[keyof T];
666
710
  /**
667
- * The result of running a tree validation function.
711
+ * A function that defines custom debounce logic for a field.
668
712
  *
669
- * The result may be one of the following:
670
- * 1. A {@link ValidationSuccess} to indicate no errors.
671
- * 2. A {@link ValidationError} without a field to indicate an error on the field being validated.
672
- * 3. A {@link ValidationError} with a field to indicate an error on the target field.
673
- * 4. A list of {@link ValidationError} with or without fields to indicate multiple errors.
713
+ * @param context The field context.
714
+ * @param abortSignal An `AbortSignal` used to communicate that the debounced operation was aborted.
715
+ * @returns A `Promise<void>` to debounce an update, or `void` to apply an update immediately.
716
+ * @template TValue The type of value stored in the field.
717
+ * @template TPathKind The kind of path the debouncer is applied to (root field, child field, or item of an array).
674
718
  *
675
- * @template E the type of error (defaults to {@link ValidationError}).
719
+ * @experimental 21.0.0
720
+ */
721
+ type Debouncer<TValue, TPathKind extends PathKind = PathKind.Root> = (context: FieldContext<TValue, TPathKind>, abortSignal: AbortSignal) => Promise<void> | void;
722
+
723
+ /**
724
+ * Options used to create a `ValidationError`.
725
+ */
726
+ interface ValidationErrorOptions {
727
+ /** Human readable error message. */
728
+ message?: string;
729
+ }
730
+ /**
731
+ * A type that requires the given type `T` to have a `field` property.
732
+ * @template T The type to add a `field` to.
676
733
  *
677
- * @category types
678
734
  * @experimental 21.0.0
679
735
  */
680
- type TreeValidationResult<E extends ValidationError.WithOptionalField = ValidationError.WithOptionalField> = ValidationSuccess | OneOrMany<E>;
736
+ type WithField<T> = T & {
737
+ field: FieldTree<unknown>;
738
+ };
681
739
  /**
682
- * A validation result where all errors explicitly define their target field.
740
+ * A type that allows the given type `T` to optionally have a `field` property.
741
+ * @template T The type to optionally add a `field` to.
683
742
  *
684
- * The result may be one of the following:
685
- * 1. A {@link ValidationSuccess} to indicate no errors.
686
- * 2. A {@link ValidationError} with a field to indicate an error on the target field.
687
- * 3. A list of {@link ValidationError} with fields to indicate multiple errors.
743
+ * @experimental 21.0.0
744
+ */
745
+ type WithOptionalField<T> = Omit<T, 'field'> & {
746
+ field?: FieldTree<unknown>;
747
+ };
748
+ /**
749
+ * A type that ensures the given type `T` does not have a `field` property.
750
+ * @template T The type to remove the `field` from.
688
751
  *
689
- * @template E the type of error (defaults to {@link ValidationError}).
752
+ * @experimental 21.0.0
753
+ */
754
+ type WithoutField<T> = T & {
755
+ field: never;
756
+ };
757
+ /**
758
+ * Create a required error associated with the target field
759
+ * @param options The validation error options
690
760
  *
691
- * @category types
692
761
  * @experimental 21.0.0
693
762
  */
694
- type ValidationResult<E extends ValidationError = ValidationError> = ValidationSuccess | OneOrMany<E>;
763
+ declare function requiredError(options: WithField<ValidationErrorOptions>): RequiredValidationError;
695
764
  /**
696
- * An asynchronous validation result where all errors explicitly define their target field.
765
+ * Create a required error
766
+ * @param options The optional validation error options
697
767
  *
698
- * The result may be one of the following:
699
- * 1. A {@link ValidationResult} to indicate the result if resolved.
700
- * 5. 'pending' if the validation is not yet resolved.
768
+ * @category validation
769
+ * @experimental 21.0.0
770
+ */
771
+ declare function requiredError(options?: ValidationErrorOptions): WithoutField<RequiredValidationError>;
772
+ /**
773
+ * Create a min value error associated with the target field
774
+ * @param min The min value constraint
775
+ * @param options The validation error options
701
776
  *
702
- * @template E the type of error (defaults to {@link ValidationError}).
777
+ * @category validation
778
+ * @experimental 21.0.0
779
+ */
780
+ declare function minError(min: number, options: WithField<ValidationErrorOptions>): MinValidationError;
781
+ /**
782
+ * Create a min value error
783
+ * @param min The min value constraint
784
+ * @param options The optional validation error options
785
+ *
786
+ * @category validation
787
+ * @experimental 21.0.0
788
+ */
789
+ declare function minError(min: number, options?: ValidationErrorOptions): WithoutField<MinValidationError>;
790
+ /**
791
+ * Create a max value error associated with the target field
792
+ * @param max The max value constraint
793
+ * @param options The validation error options
703
794
  *
704
- * @category types
795
+ * @category validation
705
796
  * @experimental 21.0.0
706
797
  */
707
- type AsyncValidationResult<E extends ValidationError = ValidationError> = ValidationResult<E> | 'pending';
798
+ declare function maxError(max: number, options: WithField<ValidationErrorOptions>): MaxValidationError;
708
799
  /**
709
- * An object that represents a tree of fields in a form. This includes both primitive value fields
710
- * (e.g. fields that contain a `string` or `number`), as well as "grouping fields" that contain
711
- * sub-fields. `FieldTree` objects are arranged in a tree whose structure mimics the structure of the
712
- * underlying data. For example a `FieldTree<{x: number}>` has a property `x` which contains a
713
- * `FieldTree<number>`. To access the state associated with a field, call it as a function.
714
- *
715
- * @template TValue The type of the data which the field is wrapped around.
716
- * @template TKey The type of the property key which this field resides under in its parent.
800
+ * Create a max value error
801
+ * @param max The max value constraint
802
+ * @param options The optional validation error options
717
803
  *
718
- * @category types
804
+ * @category validation
719
805
  * @experimental 21.0.0
720
806
  */
721
- type FieldTree<TModel, TKey extends string | number = string | number> = (() => [TModel] extends [AbstractControl] ? CompatFieldState<TModel, TKey> : FieldState<TModel, TKey>) & ([TModel] extends [AbstractControl] ? object : [TModel] extends [Array<infer U>] ? ReadonlyArrayLike<MaybeFieldTree<U, number>> : TModel extends Record<string, any> ? Subfields<TModel> : object);
807
+ declare function maxError(max: number, options?: ValidationErrorOptions): WithoutField<MaxValidationError>;
722
808
  /**
723
- * The sub-fields that a user can navigate to from a `FieldTree<TModel>`.
724
- *
725
- * @template TModel The type of the data which the parent field is wrapped around.
809
+ * Create a minLength error associated with the target field
810
+ * @param minLength The minLength constraint
811
+ * @param options The validation error options
726
812
  *
813
+ * @category validation
727
814
  * @experimental 21.0.0
728
815
  */
729
- type Subfields<TModel> = {
730
- readonly [K in keyof TModel as TModel[K] extends Function ? never : K]: MaybeFieldTree<TModel[K], string>;
731
- } & {
732
- [Symbol.iterator](): Iterator<[string, MaybeFieldTree<TModel[keyof TModel], string>]>;
733
- };
816
+ declare function minLengthError(minLength: number, options: WithField<ValidationErrorOptions>): MinLengthValidationError;
734
817
  /**
735
- * An iterable object with the same shape as a readonly array.
736
- *
737
- * @template T The array item type.
818
+ * Create a minLength error
819
+ * @param minLength The minLength constraint
820
+ * @param options The optional validation error options
738
821
  *
822
+ * @category validation
739
823
  * @experimental 21.0.0
740
824
  */
741
- type ReadonlyArrayLike<T> = Pick<ReadonlyArray<T>, number | 'length' | typeof Symbol.iterator>;
825
+ declare function minLengthError(minLength: number, options?: ValidationErrorOptions): WithoutField<MinLengthValidationError>;
742
826
  /**
743
- * Helper type for defining `FieldTree`. Given a type `TValue` that may include `undefined`, it extracts
744
- * the `undefined` outside the `FieldTree` type.
745
- *
746
- * For example `MaybeField<{a: number} | undefined, TKey>` would be equivalent to
747
- * `undefined | FieldTree<{a: number}, TKey>`.
748
- *
749
- * @template TModel The type of the data which the field is wrapped around.
750
- * @template TKey The type of the property key which this field resides under in its parent.
827
+ * Create a maxLength error associated with the target field
828
+ * @param maxLength The maxLength constraint
829
+ * @param options The validation error options
751
830
  *
831
+ * @category validation
752
832
  * @experimental 21.0.0
753
833
  */
754
- type MaybeFieldTree<TModel, TKey extends string | number = string | number> = (TModel & undefined) | FieldTree<Exclude<TModel, undefined>, TKey>;
834
+ declare function maxLengthError(maxLength: number, options: WithField<ValidationErrorOptions>): MaxLengthValidationError;
755
835
  /**
756
- * Contains all of the state (e.g. value, statuses, etc.) associated with a `FieldTree`, exposed as
757
- * signals.
836
+ * Create a maxLength error
837
+ * @param maxLength The maxLength constraint
838
+ * @param options The optional validation error options
758
839
  *
759
- * @category structure
840
+ * @category validation
760
841
  * @experimental 21.0.0
761
842
  */
762
- interface FieldState<TValue, TKey extends string | number = string | number> extends _FieldState<TValue> {
763
- /**
764
- * A signal indicating whether field value has been changed by user.
765
- */
766
- readonly dirty: Signal<boolean>;
767
- /**
768
- * A signal indicating whether a field is hidden.
769
- *
770
- * When a field is hidden it is ignored when determining the valid, touched, and dirty states.
771
- *
772
- * Note: This doesn't hide the field in the template, that must be done manually.
773
- * ```
774
- * @if (!field.hidden()) {
775
- * ...
776
- * }
777
- * ```
778
- */
779
- readonly hidden: Signal<boolean>;
780
- readonly disabledReasons: Signal<readonly DisabledReason[]>;
781
- readonly errors: Signal<ValidationError.WithField[]>;
782
- /**
783
- * A signal containing the {@link errors} of the field and its descendants.
784
- */
785
- readonly errorSummary: Signal<ValidationError.WithField[]>;
786
- /**
787
- * A signal indicating whether the field's value is currently valid.
788
- *
789
- * Note: `valid()` is not the same as `!invalid()`.
790
- * - `valid()` is `true` when there are no validation errors *and* no pending validators.
791
- * - `invalid()` is `true` when there are validation errors, regardless of pending validators.
792
- *
793
- * Ex: consider the situation where a field has 3 validators, 2 of which have no errors and 1 of
794
- * which is still pending. In this case `valid()` is `false` because of the pending validator.
795
- * However `invalid()` is also `false` because there are no errors.
796
- */
797
- readonly valid: Signal<boolean>;
798
- /**
799
- * A signal indicating whether the field's value is currently invalid.
800
- *
801
- * Note: `invalid()` is not the same as `!valid()`.
802
- * - `invalid()` is `true` when there are validation errors, regardless of pending validators.
803
- * - `valid()` is `true` when there are no validation errors *and* no pending validators.
804
- *
805
- * Ex: consider the situation where a field has 3 validators, 2 of which have no errors and 1 of
806
- * which is still pending. In this case `invalid()` is `false` because there are no errors.
807
- * However `valid()` is also `false` because of the pending validator.
808
- */
809
- readonly invalid: Signal<boolean>;
810
- /**
811
- * Whether there are any validators still pending for this field.
812
- */
813
- readonly pending: Signal<boolean>;
814
- /**
815
- * A signal indicating whether the field is currently in the process of being submitted.
816
- */
817
- readonly submitting: Signal<boolean>;
818
- /**
819
- * The property key in the parent field under which this field is stored. If the parent field is
820
- * array-valued, for example, this is the index of this field in that array.
821
- */
822
- readonly keyInParent: Signal<TKey>;
823
- /**
824
- * The {@link Field} directives that bind this field to a UI control.
825
- */
826
- readonly fieldBindings: Signal<readonly Field<unknown>[]>;
827
- /**
828
- * Reads an aggregate metadata value from the field.
829
- * @param key The metadata key to read.
830
- */
831
- metadata<M>(key: AggregateMetadataKey<M, any>): Signal<M>;
832
- /**
833
- * Reads a metadata value from the field.
834
- * @param key The metadata key to read.
835
- */
836
- metadata<M>(key: MetadataKey<M>): M | undefined;
837
- /**
838
- * Checks whether the given metadata key has been defined for this field.
839
- */
840
- hasMetadata(key: MetadataKey<any> | AggregateMetadataKey<any, any>): boolean;
841
- /**
842
- * Resets the {@link touched} and {@link dirty} state of the field and its descendants.
843
- *
844
- * Note this does not change the data model, which can be reset directly if desired.
845
- *
846
- * @param value Optional value to set to the form. If not passed, the value will not be changed.
847
- */
848
- reset(value?: TValue): void;
849
- }
843
+ declare function maxLengthError(maxLength: number, options?: ValidationErrorOptions): WithoutField<MaxLengthValidationError>;
850
844
  /**
851
- * This is FieldState also providing access to the wrapped FormControl.
845
+ * Create a pattern matching error associated with the target field
846
+ * @param pattern The violated pattern
847
+ * @param options The validation error options
852
848
  *
853
- * @category interop
849
+ * @category validation
854
850
  * @experimental 21.0.0
855
851
  */
856
- type CompatFieldState<TControl extends AbstractControl, TKey extends string | number = string | number> = FieldState<TControl extends AbstractControl<unknown, infer TValue> ? TValue : never, TKey> & {
857
- control: Signal<TControl>;
858
- };
852
+ declare function patternError(pattern: RegExp, options: WithField<ValidationErrorOptions>): PatternValidationError;
859
853
  /**
860
- * Allows declaring whether the Rules are supported for a given path.
854
+ * Create a pattern matching error
855
+ * @param pattern The violated pattern
856
+ * @param options The optional validation error options
861
857
  *
858
+ * @category validation
862
859
  * @experimental 21.0.0
863
- **/
864
- type SchemaPathRules = SchemaPathRules.Supported | SchemaPathRules.Unsupported;
865
- declare namespace SchemaPathRules {
866
- /**
867
- * Used for paths that support settings rules.
868
- */
869
- type Supported = 1;
870
- /**
871
- * Used for paths that do not support settings rules, e.g., compatPath.
872
- */
873
- type Unsupported = 2;
874
- }
860
+ */
861
+ declare function patternError(pattern: RegExp, options?: ValidationErrorOptions): WithoutField<PatternValidationError>;
875
862
  /**
876
- * An object that represents a location in the `FieldTree` tree structure and is used to bind logic to a
877
- * particular part of the structure prior to the creation of the form. Because the `FieldPath`
878
- * exists prior to the form's creation, it cannot be used to access any of the field state.
879
- *
880
- * @template TValue The type of the data which the form is wrapped around.
881
- * @template TPathKind The kind of path (root field, child field, or item of an array)
863
+ * Create an email format error associated with the target field
864
+ * @param options The validation error options
882
865
  *
883
- * @category types
866
+ * @category validation
884
867
  * @experimental 21.0.0
885
868
  */
886
- type SchemaPath<TValue, TSupportsRules extends SchemaPathRules = SchemaPathRules.Supported, TPathKind extends PathKind = PathKind.Root> = {
887
- [ɵɵTYPE]: {
888
- value: () => TValue;
889
- supportsRules: TSupportsRules;
890
- pathKind: TPathKind;
891
- };
892
- };
869
+ declare function emailError(options: WithField<ValidationErrorOptions>): EmailValidationError;
893
870
  /**
894
- * Schema path used if the value is an AbstractControl.
871
+ * Create an email format error
872
+ * @param options The optional validation error options
895
873
  *
896
- * @category interop
874
+ * @category validation
897
875
  * @experimental 21.0.0
898
876
  */
899
- type CompatSchemaPath<TControl extends AbstractControl, TPathKind extends PathKind = PathKind.Root> = SchemaPath<TControl extends AbstractControl<unknown, infer TValue> ? TValue : never, SchemaPathRules.Unsupported, TPathKind> & {
900
- [ɵɵTYPE]: {
901
- control: TControl;
902
- };
903
- };
877
+ declare function emailError(options?: ValidationErrorOptions): WithoutField<EmailValidationError>;
904
878
  /**
905
- * Nested schema path.
906
- *
907
- * It mirrors the structure of a given data structure, and allows applying rules to the appropriate
908
- * fields.
879
+ * Create a standard schema issue error associated with the target field
880
+ * @param issue The standard schema issue
881
+ * @param options The validation error options
909
882
  *
883
+ * @category validation
910
884
  * @experimental 21.0.0
911
885
  */
912
- type SchemaPathTree<TModel, TPathKind extends PathKind = PathKind.Root> = ([TModel] extends [AbstractControl] ? CompatSchemaPath<TModel, TPathKind> : SchemaPath<TModel, SchemaPathRules.Supported, TPathKind>) & (TModel extends AbstractControl ? unknown : TModel extends Array<any> ? unknown : TModel extends Record<string, any> ? {
913
- [K in keyof TModel]: MaybeSchemaPathTree<TModel[K], PathKind.Child>;
914
- } : unknown);
886
+ declare function standardSchemaError(issue: StandardSchemaV1.Issue, options: WithField<ValidationErrorOptions>): StandardSchemaValidationError;
915
887
  /**
916
- * Helper type for defining `FieldPath`. Given a type `TValue` that may include `undefined`, it
917
- * extracts the `undefined` outside the `FieldPath` type.
918
- *
919
- * For example `MaybeFieldPath<{a: number} | undefined, PathKind.Child>` would be equivalent to
920
- * `undefined | FieldTree<{a: number}, PathKind.child>`.
921
- *
922
- * @template TValue The type of the data which the field is wrapped around.
923
- * @template TPathKind The kind of path (root field, child field, or item of an array)
888
+ * Create a standard schema issue error
889
+ * @param issue The standard schema issue
890
+ * @param options The optional validation error options
924
891
  *
892
+ * @category validation
925
893
  * @experimental 21.0.0
926
894
  */
927
- type MaybeSchemaPathTree<TModel, TPathKind extends PathKind = PathKind.Root> = (TModel & undefined) | SchemaPathTree<Exclude<TModel, undefined>, TPathKind>;
895
+ declare function standardSchemaError(issue: StandardSchemaV1.Issue, options?: ValidationErrorOptions): WithoutField<StandardSchemaValidationError>;
928
896
  /**
929
- * Defines logic for a form.
897
+ * Create a custom error associated with the target field
898
+ * @param obj The object to create an error from
930
899
  *
931
- * @template TValue The type of data stored in the form that this schema is attached to.
900
+ * @category validation
901
+ * @experimental 21.0.0
902
+ */
903
+ declare function customError<E extends Partial<ValidationError.WithField>>(obj: WithField<E>): CustomValidationError;
904
+ /**
905
+ * Create a custom error
906
+ * @param obj The object to create an error from
932
907
  *
933
- * @category types
908
+ * @category validation
934
909
  * @experimental 21.0.0
935
910
  */
936
- type Schema<in TModel> = {
937
- [ɵɵTYPE]: SchemaFn<TModel, PathKind.Root>;
938
- };
911
+ declare function customError<E extends Partial<ValidationError.WithField>>(obj?: E): WithoutField<CustomValidationError>;
939
912
  /**
940
- * Function that defines rules for a schema.
913
+ * Common interface for all validation errors.
941
914
  *
942
- * @template TModel The type of data stored in the form that this schema function is attached to.
943
- * @template TPathKind The kind of path this schema function can be bound to.
915
+ * This can be returned from validators.
944
916
  *
945
- * @category types
917
+ * It's also used by the creation functions to create an instance
918
+ * (e.g. `requiredError`, `minError`, etc.).
919
+ *
920
+ * @category validation
946
921
  * @experimental 21.0.0
947
922
  */
948
- type SchemaFn<TModel, TPathKind extends PathKind = PathKind.Root> = (p: SchemaPathTree<TModel, TPathKind>) => void;
923
+ interface ValidationError {
924
+ /** Identifies the kind of error. */
925
+ readonly kind: string;
926
+ /** Human readable error message. */
927
+ readonly message?: string;
928
+ }
929
+ declare namespace ValidationError {
930
+ /**
931
+ * Validation error with a field.
932
+ *
933
+ * This is returned from field state, e.g., catField.errors() would be of a list of errors with
934
+ * `field: catField` bound to state.
935
+ */
936
+ interface WithField extends ValidationError {
937
+ /** The field associated with this error. */
938
+ readonly field: FieldTree<unknown>;
939
+ }
940
+ /**
941
+ * Validation error with optional field.
942
+ *
943
+ * This is generally used in places where the result might have a field.
944
+ * e.g., as a result of a `validateTree`, or when handling form submission.
945
+ */
946
+ interface WithOptionalField extends ValidationError {
947
+ /** The field associated with this error. */
948
+ readonly field?: FieldTree<unknown>;
949
+ }
950
+ /**
951
+ * Validation error with no field.
952
+ *
953
+ * This is used to strongly enforce that fields are not allowed in validation result.
954
+ */
955
+ interface WithoutField extends ValidationError {
956
+ /** The field associated with this error. */
957
+ readonly field?: never;
958
+ }
959
+ }
949
960
  /**
950
- * A schema or schema definition function.
951
- *
952
- * @template TModel The type of data stored in the form that this schema function is attached to.
953
- * @template TPathKind The kind of path this schema function can be bound to.
961
+ * A custom error that may contain additional properties
954
962
  *
955
- * @category types
963
+ * @category validation
956
964
  * @experimental 21.0.0
957
965
  */
958
- type SchemaOrSchemaFn<TModel, TPathKind extends PathKind = PathKind.Root> = Schema<TModel> | SchemaFn<TModel, TPathKind>;
966
+ declare class CustomValidationError implements ValidationError {
967
+ /** Brand the class to avoid Typescript structural matching */
968
+ private __brand;
969
+ /**
970
+ * Allow the user to attach arbitrary other properties.
971
+ */
972
+ [key: PropertyKey]: unknown;
973
+ /** Identifies the kind of error. */
974
+ readonly kind: string;
975
+ /** The field associated with this error. */
976
+ readonly field: FieldTree<unknown>;
977
+ /** Human readable error message. */
978
+ readonly message?: string;
979
+ constructor(options?: ValidationErrorOptions);
980
+ }
959
981
  /**
960
- * A function that receives the `FieldContext` for the field the logic is bound to and returns
961
- * a specific result type.
962
- *
963
- * @template TValue The data type for the field the logic is bound to.
964
- * @template TReturn The type of the result returned by the logic function.
965
- * @template TPathKind The kind of path the logic is applied to (root field, child field, or item of an array)
982
+ * Internal version of `NgValidationError`, we create this separately so we can change its type on
983
+ * the exported version to a type union of the possible sub-classes.
966
984
  *
967
- * @category types
968
985
  * @experimental 21.0.0
969
986
  */
970
- type LogicFn<TValue, TReturn, TPathKind extends PathKind = PathKind.Root> = (ctx: FieldContext<TValue, TPathKind>) => TReturn;
987
+ declare abstract class _NgValidationError implements ValidationError {
988
+ /** Brand the class to avoid Typescript structural matching */
989
+ private __brand;
990
+ /** Identifies the kind of error. */
991
+ readonly kind: string;
992
+ /** The field associated with this error. */
993
+ readonly field: FieldTree<unknown>;
994
+ /** Human readable error message. */
995
+ readonly message?: string;
996
+ constructor(options?: ValidationErrorOptions);
997
+ }
971
998
  /**
972
- * A function that takes the `FieldContext` for the field being validated and returns a
973
- * `ValidationResult` indicating errors for the field.
974
- *
975
- * @template TValue The type of value stored in the field being validated
976
- * @template TPathKind The kind of path being validated (root field, child field, or item of an array)
999
+ * An error used to indicate that a required field is empty.
977
1000
  *
978
1001
  * @category validation
979
1002
  * @experimental 21.0.0
980
1003
  */
981
- type FieldValidator<TValue, TPathKind extends PathKind = PathKind.Root> = LogicFn<TValue, ValidationResult<ValidationError.WithoutField>, TPathKind>;
1004
+ declare class RequiredValidationError extends _NgValidationError {
1005
+ readonly kind = "required";
1006
+ }
982
1007
  /**
983
- * A function that takes the `FieldContext` for the field being validated and returns a
984
- * `TreeValidationResult` indicating errors for the field and its sub-fields.
985
- *
986
- * @template TValue The type of value stored in the field being validated
987
- * @template TPathKind The kind of path being validated (root field, child field, or item of an array)
1008
+ * An error used to indicate that a value is lower than the minimum allowed.
988
1009
  *
989
- * @category types
1010
+ * @category validation
990
1011
  * @experimental 21.0.0
991
1012
  */
992
- type TreeValidator<TValue, TPathKind extends PathKind = PathKind.Root> = LogicFn<TValue, TreeValidationResult, TPathKind>;
1013
+ declare class MinValidationError extends _NgValidationError {
1014
+ readonly min: number;
1015
+ readonly kind = "min";
1016
+ constructor(min: number, options?: ValidationErrorOptions);
1017
+ }
993
1018
  /**
994
- * A function that takes the `FieldContext` for the field being validated and returns a
995
- * `ValidationResult` indicating errors for the field and its sub-fields. In a `Validator` all
996
- * errors must explicitly define their target field.
997
- *
998
- * @template TValue The type of value stored in the field being validated
999
- * @template TPathKind The kind of path being validated (root field, child field, or item of an array)
1019
+ * An error used to indicate that a value is higher than the maximum allowed.
1000
1020
  *
1001
- * @category types
1021
+ * @category validation
1002
1022
  * @experimental 21.0.0
1003
1023
  */
1004
- type Validator<TValue, TPathKind extends PathKind = PathKind.Root> = LogicFn<TValue, ValidationResult, TPathKind>;
1024
+ declare class MaxValidationError extends _NgValidationError {
1025
+ readonly max: number;
1026
+ readonly kind = "max";
1027
+ constructor(max: number, options?: ValidationErrorOptions);
1028
+ }
1005
1029
  /**
1006
- * Provides access to the state of the current field as well as functions that can be used to look
1007
- * up state of other fields based on a `FieldPath`.
1030
+ * An error used to indicate that a value is shorter than the minimum allowed length.
1008
1031
  *
1009
- * @category types
1032
+ * @category validation
1010
1033
  * @experimental 21.0.0
1011
1034
  */
1012
- type FieldContext<TValue, TPathKind extends PathKind = PathKind.Root> = TPathKind extends PathKind.Item ? ItemFieldContext<TValue> : TPathKind extends PathKind.Child ? ChildFieldContext<TValue> : RootFieldContext<TValue>;
1035
+ declare class MinLengthValidationError extends _NgValidationError {
1036
+ readonly minLength: number;
1037
+ readonly kind = "minLength";
1038
+ constructor(minLength: number, options?: ValidationErrorOptions);
1039
+ }
1013
1040
  /**
1014
- * The base field context that is available for all fields.
1041
+ * An error used to indicate that a value is longer than the maximum allowed length.
1015
1042
  *
1043
+ * @category validation
1016
1044
  * @experimental 21.0.0
1017
1045
  */
1018
- interface RootFieldContext<TValue> {
1019
- /** A signal containing the value of the current field. */
1020
- readonly value: Signal<TValue>;
1021
- /** The state of the current field. */
1022
- readonly state: FieldState<TValue>;
1023
- /** The current field. */
1024
- readonly field: FieldTree<TValue>;
1025
- /** Gets the value of the field represented by the given path. */
1026
- valueOf<PValue>(p: SchemaPath<PValue, SchemaPathRules>): PValue;
1027
- /** Gets the state of the field represented by the given path. */
1028
- stateOf<PControl extends AbstractControl>(p: CompatSchemaPath<PControl>): CompatFieldState<PControl>;
1029
- stateOf<PValue>(p: SchemaPath<PValue, SchemaPathRules>): FieldState<PValue>;
1030
- /** Gets the field represented by the given path. */
1031
- fieldTreeOf<PModel>(p: SchemaPathTree<PModel>): FieldTree<PModel>;
1032
- /** The list of keys that lead from the root field to the current field. */
1033
- readonly pathKeys: Signal<readonly string[]>;
1046
+ declare class MaxLengthValidationError extends _NgValidationError {
1047
+ readonly maxLength: number;
1048
+ readonly kind = "maxLength";
1049
+ constructor(maxLength: number, options?: ValidationErrorOptions);
1034
1050
  }
1035
1051
  /**
1036
- * Field context that is available for all fields that are a child of another field.
1052
+ * An error used to indicate that a value does not match the required pattern.
1037
1053
  *
1038
- * @category structure
1054
+ * @category validation
1039
1055
  * @experimental 21.0.0
1040
1056
  */
1041
- interface ChildFieldContext<TValue> extends RootFieldContext<TValue> {
1042
- /** The key of the current field in its parent field. */
1043
- readonly key: Signal<string>;
1057
+ declare class PatternValidationError extends _NgValidationError {
1058
+ readonly pattern: RegExp;
1059
+ readonly kind = "pattern";
1060
+ constructor(pattern: RegExp, options?: ValidationErrorOptions);
1044
1061
  }
1045
1062
  /**
1046
- * Field context that is available for all fields that are an item in an array field.
1063
+ * An error used to indicate that a value is not a valid email.
1047
1064
  *
1065
+ * @category validation
1048
1066
  * @experimental 21.0.0
1049
1067
  */
1050
- interface ItemFieldContext<TValue> extends ChildFieldContext<TValue> {
1051
- /** The index of the current field in its parent field. */
1052
- readonly index: Signal<number>;
1068
+ declare class EmailValidationError extends _NgValidationError {
1069
+ readonly kind = "email";
1053
1070
  }
1054
1071
  /**
1055
- * Gets the item type of an object that is possibly an array.
1072
+ * An error used to indicate an issue validating against a standard schema.
1056
1073
  *
1074
+ * @category validation
1057
1075
  * @experimental 21.0.0
1058
1076
  */
1059
- type ItemType<T extends Object> = T extends ReadonlyArray<any> ? T[number] : T[keyof T];
1077
+ declare class StandardSchemaValidationError extends _NgValidationError {
1078
+ readonly issue: StandardSchemaV1.Issue;
1079
+ readonly kind = "standardSchema";
1080
+ constructor(issue: StandardSchemaV1.Issue, options?: ValidationErrorOptions);
1081
+ }
1060
1082
  /**
1061
- * A function that defines custom debounce logic for a field.
1083
+ * The base class for all built-in, non-custom errors. This class can be used to check if an error
1084
+ * is one of the standard kinds, allowing you to switch on the kind to further narrow the type.
1062
1085
  *
1063
- * @param context The field context.
1064
- * @param abortSignal An `AbortSignal` used to communicate that the debounced operation was aborted.
1065
- * @returns A `Promise<void>` to debounce an update, or `void` to apply an update immediately.
1066
- * @template TValue The type of value stored in the field.
1067
- * @template TPathKind The kind of path the debouncer is applied to (root field, child field, or item of an array).
1086
+ * @example
1087
+ * ```ts
1088
+ * const f = form(...);
1089
+ * for (const e of form().errors()) {
1090
+ * if (e instanceof NgValidationError) {
1091
+ * switch(e.kind) {
1092
+ * case 'required':
1093
+ * console.log('This is required!');
1094
+ * break;
1095
+ * case 'min':
1096
+ * console.log(`Must be at least ${e.min}`);
1097
+ * break;
1098
+ * ...
1099
+ * }
1100
+ * }
1101
+ * }
1102
+ * ```
1068
1103
  *
1104
+ * @category validation
1069
1105
  * @experimental 21.0.0
1070
1106
  */
1071
- type Debouncer<TValue, TPathKind extends PathKind = PathKind.Root> = (context: FieldContext<TValue, TPathKind>, abortSignal: AbortSignal) => Promise<void> | void;
1107
+ declare const NgValidationError: abstract new () => NgValidationError;
1108
+ type NgValidationError = RequiredValidationError | MinValidationError | MaxValidationError | MinLengthValidationError | MaxLengthValidationError | PatternValidationError | EmailValidationError | StandardSchemaValidationError;
1072
1109
 
1073
1110
  /**
1074
1111
  * Configuration options for signal forms.
@@ -1205,41 +1242,27 @@ declare class LogicContainer {
1205
1242
  readonly syncTreeErrors: ArrayMergeIgnoreLogic<ValidationError.WithField, null>;
1206
1243
  /** Logic that produces asynchronous validation results (errors or 'pending'). */
1207
1244
  readonly asyncErrors: ArrayMergeIgnoreLogic<ValidationError.WithField | 'pending', null>;
1208
- /** A map of aggregate metadata keys to the `AbstractLogic` instances that compute their values. */
1209
- private readonly aggregateMetadataKeys;
1210
- /** A map of metadata keys to the factory functions that create their values. */
1211
- private readonly metadataFactories;
1245
+ /** A map of metadata keys to the `AbstractLogic` instances that compute their values. */
1246
+ private readonly metadata;
1212
1247
  /**
1213
1248
  * Constructs a new `Logic` container.
1214
1249
  * @param predicates An array of predicates that must all be true for the logic
1215
1250
  * functions within this container to be active.
1216
1251
  */
1217
1252
  constructor(predicates: ReadonlyArray<BoundPredicate>);
1218
- /** Checks whether there is logic for the given aggregate metadata key. */
1219
- hasAggregateMetadata(key: AggregateMetadataKey<any, any>): boolean;
1220
- /**
1221
- * Gets an iterable of [aggregate metadata, logic function] pairs.
1222
- * @returns An iterable of aggregate metadata entries.
1223
- */
1224
- getAggregateMetadataEntries(): MapIterator<[AggregateMetadataKey<unknown, unknown>, AbstractLogic<unknown, unknown>]>;
1253
+ /** Checks whether there is logic for the given metadata key. */
1254
+ hasMetadata(key: MetadataKey<any, any, any>): boolean;
1225
1255
  /**
1226
- * Gets an iterable of [metadata, value factory function] pairs.
1227
- * @returns An iterable of metadata factory entries.
1256
+ * Gets an iterable of [metadata key, logic function] pairs.
1257
+ * @returns An iterable of metadata keys.
1228
1258
  */
1229
- getMetadataFactoryEntries(): MapIterator<[MetadataKey<unknown>, (ctx: FieldContext<unknown>) => unknown]>;
1259
+ getMetadataKeys(): MapIterator<MetadataKey<unknown, unknown, unknown>>;
1230
1260
  /**
1231
- * Retrieves or creates the `AbstractLogic` for a given aggregate metadata key.
1232
- * @param key The `AggregateMetadataKey` for which to get the logic.
1261
+ * Retrieves or creates the `AbstractLogic` for a given metadata key.
1262
+ * @param key The `MetadataKey` for which to get the logic.
1233
1263
  * @returns The `AbstractLogic` associated with the key.
1234
1264
  */
1235
- getAggregateMetadata<T>(key: AggregateMetadataKey<any, T>): AbstractLogic<T>;
1236
- /**
1237
- * Adds a factory function for a given metadata key.
1238
- * @param key The `MetadataKey` to associate the factory with.
1239
- * @param factory The factory function.
1240
- * @throws If a factory is already defined for the given key.
1241
- */
1242
- addMetadataFactory(key: MetadataKey<unknown>, factory: (ctx: FieldContext<unknown>) => unknown): void;
1265
+ getMetadata<T>(key: MetadataKey<any, T, any>): AbstractLogic<T>;
1243
1266
  /**
1244
1267
  * Merges logic from another `Logic` instance into this one.
1245
1268
  * @param other The `Logic` instance to merge from.
@@ -1271,10 +1294,8 @@ declare abstract class AbstractLogicNodeBuilder {
1271
1294
  abstract addSyncTreeErrorRule(logic: LogicFn<any, ValidationResult>): void;
1272
1295
  /** Adds a rule for asynchronous validation errors for a field. */
1273
1296
  abstract addAsyncErrorRule(logic: LogicFn<any, AsyncValidationResult>): void;
1274
- /** Adds a rule to compute aggregate metadata for a field. */
1275
- abstract addAggregateMetadataRule<M>(key: AggregateMetadataKey<unknown, M>, logic: LogicFn<any, M>): void;
1276
- /** Adds a factory function to produce a data value associated with a field. */
1277
- abstract addMetadataFactory<D>(key: MetadataKey<D>, factory: (ctx: FieldContext<any>) => D): void;
1297
+ /** Adds a rule to compute metadata for a field. */
1298
+ abstract addMetadataRule<M>(key: MetadataKey<unknown, M, unknown>, logic: LogicFn<any, M>): void;
1278
1299
  /**
1279
1300
  * Gets a builder for a child node associated with the given property key.
1280
1301
  * @param key The property key of the child.
@@ -1320,8 +1341,7 @@ declare class LogicNodeBuilder extends AbstractLogicNodeBuilder {
1320
1341
  addSyncErrorRule(logic: LogicFn<any, ValidationResult<ValidationError.WithField>>): void;
1321
1342
  addSyncTreeErrorRule(logic: LogicFn<any, ValidationResult<ValidationError.WithField>>): void;
1322
1343
  addAsyncErrorRule(logic: LogicFn<any, AsyncValidationResult<ValidationError.WithField>>): void;
1323
- addAggregateMetadataRule<T>(key: AggregateMetadataKey<any, T>, logic: LogicFn<any, T>): void;
1324
- addMetadataFactory<D>(key: MetadataKey<D>, factory: (ctx: FieldContext<any>) => D): void;
1344
+ addMetadataRule<T>(key: MetadataKey<unknown, T, any>, logic: LogicFn<any, T>): void;
1325
1345
  getChild(key: PropertyKey): LogicNodeBuilder;
1326
1346
  hasLogic(builder: AbstractLogicNodeBuilder): boolean;
1327
1347
  /**
@@ -1450,13 +1470,13 @@ declare class FieldPathNode {
1450
1470
  */
1451
1471
  declare class FieldMetadataState {
1452
1472
  private readonly node;
1453
- /** A map of all `MetadataKey` and `AggregateMetadataKey` that have been defined for this field. */
1473
+ /** A map of all `MetadataKey` that have been defined for this field. */
1454
1474
  private readonly metadata;
1455
1475
  constructor(node: FieldNode);
1456
- /** Gets the value of a `MetadataKey` or `AggregateMetadataKey` for the field. */
1457
- get<T>(key: MetadataKey<T> | AggregateMetadataKey<T, unknown>): T | undefined | Signal<T>;
1476
+ /** Gets the value of an `MetadataKey` for the field. */
1477
+ get<T>(key: MetadataKey<T, unknown, unknown>): T | undefined;
1458
1478
  /** Checks whether the current metadata state has the given metadata key. */
1459
- has(key: MetadataKey<any> | AggregateMetadataKey<any, any>): boolean;
1479
+ has(key: MetadataKey<any, any, any>): boolean;
1460
1480
  }
1461
1481
 
1462
1482
  /**
@@ -1695,6 +1715,7 @@ declare class FieldNode implements FieldState<unknown> {
1695
1715
  * Proxy to this node which allows navigation of the form graph below it.
1696
1716
  */
1697
1717
  readonly fieldProxy: FieldTree<any>;
1718
+ private readonly pathNode;
1698
1719
  constructor(options: FieldNodeOptions);
1699
1720
  /**
1700
1721
  * The `AbortController` for the currently debounced sync, or `undefined` if there is none.
@@ -1723,16 +1744,14 @@ declare class FieldNode implements FieldState<unknown> {
1723
1744
  get fieldBindings(): Signal<readonly Field<unknown>[]>;
1724
1745
  get submitting(): Signal<boolean>;
1725
1746
  get name(): Signal<string>;
1726
- private metadataOrUndefined;
1727
1747
  get max(): Signal<number | undefined> | undefined;
1728
1748
  get maxLength(): Signal<number | undefined> | undefined;
1729
1749
  get min(): Signal<number | undefined> | undefined;
1730
1750
  get minLength(): Signal<number | undefined> | undefined;
1731
1751
  get pattern(): Signal<readonly RegExp[]>;
1732
1752
  get required(): Signal<boolean>;
1733
- metadata<M>(key: AggregateMetadataKey<M, any>): Signal<M>;
1734
- metadata<M>(key: MetadataKey<M>): M | undefined;
1735
- hasMetadata(key: MetadataKey<any> | AggregateMetadataKey<any, any>): boolean;
1753
+ metadata<M>(key: MetadataKey<M, any, any>): M | undefined;
1754
+ hasMetadata(key: MetadataKey<any, any, any>): boolean;
1736
1755
  /**
1737
1756
  * Marks this specific field as touched.
1738
1757
  */
@@ -1772,11 +1791,8 @@ declare class FieldNode implements FieldState<unknown> {
1772
1791
  * Creates a new root field node for a new form.
1773
1792
  */
1774
1793
  static newRoot<T>(fieldManager: FormFieldManager, value: WritableSignal<T>, pathNode: FieldPathNode, adapter: FieldAdapter): FieldNode;
1775
- /**
1776
- * Creates a child field node based on the given options.
1777
- */
1778
- private static newChild;
1779
1794
  createStructure(options: FieldNodeOptions): RootFieldNodeStructure | ChildFieldNodeStructure;
1795
+ private newChild;
1780
1796
  }
1781
1797
  /**
1782
1798
  * Field node of a field that has children.
@@ -1798,12 +1814,16 @@ interface ParentFieldNode extends FieldNode {
1798
1814
  type TrackingKey = PropertyKey & {
1799
1815
  __brand: 'FieldIdentity';
1800
1816
  };
1817
+ type ChildNodeCtor = (key: string, trackingKey: TrackingKey | undefined, isArray: boolean) => FieldNode;
1801
1818
  /** Structural component of a `FieldNode` which tracks its path, parent, and children. */
1802
1819
  declare abstract class FieldNodeStructure {
1803
- /** The logic to apply to this field. */
1804
- readonly logic: LogicNode;
1805
- /** Computed map of child fields, based on the current value of this field. */
1806
- abstract readonly childrenMap: Signal<Map<TrackingKey, FieldNode> | undefined>;
1820
+ /**
1821
+ * Computed map of child fields, based on the current value of this field.
1822
+ *
1823
+ * This structure reacts to `this.value` and produces a new `ChildrenData` when the
1824
+ * value changes structurally (fields added/removed/moved).
1825
+ */
1826
+ protected abstract readonly childrenMap: Signal<ChildrenData | undefined>;
1807
1827
  /** The field's value. */
1808
1828
  abstract readonly value: WritableSignal<unknown>;
1809
1829
  /**
@@ -1819,33 +1839,60 @@ declare abstract class FieldNodeStructure {
1819
1839
  abstract readonly pathKeys: Signal<readonly string[]>;
1820
1840
  /** The parent field of this field. */
1821
1841
  abstract readonly parent: FieldNode | undefined;
1842
+ readonly logic: LogicNode;
1843
+ readonly node: FieldNode;
1844
+ readonly createChildNode: ChildNodeCtor;
1822
1845
  /** Added to array elements for tracking purposes. */
1823
1846
  readonly identitySymbol: symbol;
1824
1847
  /** Lazily initialized injector. Do not access directly, access via `injector` getter instead. */
1825
1848
  private _injector;
1826
1849
  /** Lazily initialized injector. */
1827
1850
  get injector(): DestroyableInjector;
1828
- constructor(
1829
- /** The logic to apply to this field. */
1830
- logic: LogicNode);
1851
+ constructor(logic: LogicNode, node: FieldNode, createChildNode: ChildNodeCtor);
1831
1852
  /** Gets the child fields of this field. */
1832
1853
  children(): Iterable<FieldNode>;
1833
1854
  /** Retrieve a child `FieldNode` of this node by property key. */
1834
1855
  getChild(key: PropertyKey): FieldNode | undefined;
1856
+ /**
1857
+ * Perform a reduction over a field's children (if any) and return the result.
1858
+ *
1859
+ * Optionally, the reduction is short circuited based on the provided `shortCircuit` function.
1860
+ */
1861
+ reduceChildren<T>(initialValue: T, fn: (child: FieldNode, value: T) => T, shortCircuit?: (value: T) => boolean): T;
1835
1862
  /** Destroys the field when it is no longer needed. */
1836
1863
  destroy(): void;
1864
+ /**
1865
+ * Creates a keyInParent signal for a field node.
1866
+ *
1867
+ * For root nodes, returns ROOT_KEY_IN_PARENT which throws when accessed.
1868
+ * For child nodes, creates a computed that tracks the field's current key in its parent,
1869
+ * with special handling for tracked array elements.
1870
+ *
1871
+ * @param options The field node options
1872
+ * @param identityInParent The tracking identity (only for tracked array children)
1873
+ * @param initialKeyInParent The initial key in parent (only for child nodes)
1874
+ * @returns A signal representing the field's key in its parent
1875
+ */
1876
+ protected createKeyInParent(options: FieldNodeOptions, identityInParent: TrackingKey | undefined, initialKeyInParent: string | undefined): Signal<string>;
1877
+ protected createChildrenMap(): Signal<ChildrenData | undefined>;
1878
+ /**
1879
+ * Creates a "reader" computed for the given key.
1880
+ *
1881
+ * A reader is a computed signal that memoizes the access of the `FieldNode` stored at this key
1882
+ * (or returns `undefined` if no such field exists). Accessing fields via the reader ensures that
1883
+ * reactive consumers aren't notified unless the field at a key actually changes.
1884
+ */
1885
+ private createReader;
1837
1886
  }
1838
1887
  /** The structural component of a `FieldNode` that is the root of its field tree. */
1839
1888
  declare class RootFieldNodeStructure extends FieldNodeStructure {
1840
- /** The full field node that corresponds to this structure. */
1841
- private readonly node;
1842
1889
  readonly fieldManager: FormFieldManager;
1843
1890
  readonly value: WritableSignal<unknown>;
1844
1891
  get parent(): undefined;
1845
1892
  get root(): FieldNode;
1846
1893
  get pathKeys(): Signal<readonly string[]>;
1847
1894
  get keyInParent(): Signal<string>;
1848
- readonly childrenMap: Signal<Map<TrackingKey, FieldNode> | undefined>;
1895
+ protected readonly childrenMap: Signal<ChildrenData | undefined>;
1849
1896
  /**
1850
1897
  * Creates the structure for the root node of a field tree.
1851
1898
  *
@@ -1859,16 +1906,17 @@ declare class RootFieldNodeStructure extends FieldNodeStructure {
1859
1906
  */
1860
1907
  constructor(
1861
1908
  /** The full field node that corresponds to this structure. */
1862
- node: FieldNode, pathNode: FieldPathNode, logic: LogicNode, fieldManager: FormFieldManager, value: WritableSignal<unknown>, adapter: FieldAdapter, createChildNode: (options: ChildFieldNodeOptions) => FieldNode);
1909
+ node: FieldNode, logic: LogicNode, fieldManager: FormFieldManager, value: WritableSignal<unknown>, createChildNode: ChildNodeCtor);
1863
1910
  }
1864
1911
  /** The structural component of a child `FieldNode` within a field tree. */
1865
1912
  declare class ChildFieldNodeStructure extends FieldNodeStructure {
1913
+ readonly logic: LogicNode;
1866
1914
  readonly parent: ParentFieldNode;
1867
1915
  readonly root: FieldNode;
1868
1916
  readonly pathKeys: Signal<readonly string[]>;
1869
1917
  readonly keyInParent: Signal<string>;
1870
1918
  readonly value: WritableSignal<unknown>;
1871
- readonly childrenMap: Signal<Map<TrackingKey, FieldNode> | undefined>;
1919
+ readonly childrenMap: Signal<ChildrenData | undefined>;
1872
1920
  get fieldManager(): FormFieldManager;
1873
1921
  /**
1874
1922
  * Creates the structure for a child field node in a field tree.
@@ -1882,7 +1930,7 @@ declare class ChildFieldNodeStructure extends FieldNodeStructure {
1882
1930
  * @param adapter Adapter that knows how to create new fields and appropriate state.
1883
1931
  * @param createChildNode A factory function to create child nodes for this field.
1884
1932
  */
1885
- constructor(node: FieldNode, pathNode: FieldPathNode, logic: LogicNode, parent: ParentFieldNode, identityInParent: TrackingKey | undefined, initialKeyInParent: string, adapter: FieldAdapter, createChildNode: (options: ChildFieldNodeOptions) => FieldNode);
1933
+ constructor(node: FieldNode, logic: LogicNode, parent: ParentFieldNode, identityInParent: TrackingKey | undefined, initialKeyInParent: string, createChildNode: ChildNodeCtor);
1886
1934
  }
1887
1935
  /** Options passed when constructing a root field node. */
1888
1936
  interface RootFieldNodeOptions {
@@ -1918,6 +1966,38 @@ interface ChildFieldNodeOptions {
1918
1966
  }
1919
1967
  /** Options passed when constructing a field node. */
1920
1968
  type FieldNodeOptions = RootFieldNodeOptions | ChildFieldNodeOptions;
1969
+ /**
1970
+ * Derived data regarding child fields for a specific parent field.
1971
+ */
1972
+ interface ChildrenData {
1973
+ /**
1974
+ * Tracks `ChildData` for each property key within the parent.
1975
+ */
1976
+ readonly byPropertyKey: ReadonlyMap<string, ChildData>;
1977
+ /**
1978
+ * Tracks the instance of child `FieldNode`s by their tracking key, which is always 1:1 with the
1979
+ * fields, even if they move around in the parent.
1980
+ */
1981
+ readonly byTrackingKey?: ReadonlyMap<TrackingKey, FieldNode>;
1982
+ }
1983
+ /**
1984
+ * Data for a specific child within a parent.
1985
+ */
1986
+ interface ChildData {
1987
+ /**
1988
+ * A computed signal to access the `FieldNode` currently stored at a specific key.
1989
+ *
1990
+ * Because this is a computed, it only updates whenever the `FieldNode` at that key changes.
1991
+ * Because `ChildData` is always associated with a specific key via `ChildrenData.byPropertyKey`,
1992
+ * this computed gives a stable way to watch the field stored for a given property and only
1993
+ * receives notifications when that field changes.
1994
+ */
1995
+ readonly reader: Signal<FieldNode | undefined>;
1996
+ /**
1997
+ * The child `FieldNode` currently stored at this key.
1998
+ */
1999
+ node: FieldNode;
2000
+ }
1921
2001
 
1922
2002
  /**
1923
2003
  * Manages the collection of fields associated with a given `form`.
@@ -2264,5 +2344,5 @@ declare function submit<TModel>(form: FieldTree<TModel>, action: (form: FieldTre
2264
2344
  */
2265
2345
  declare function schema<TValue>(fn: SchemaFn<TValue>): Schema<TValue>;
2266
2346
 
2267
- export { AggregateMetadataKey, CustomValidationError, EmailValidationError, FIELD, Field, MAX, MAX_LENGTH, MIN, MIN_LENGTH, MaxLengthValidationError, MaxValidationError, MetadataKey, MinLengthValidationError, MinValidationError, NgValidationError, PATTERN, PathKind, PatternValidationError, REQUIRED, RequiredValidationError, SchemaPathRules, StandardSchemaValidationError, ValidationError, andMetadataKey, apply, applyEach, applyWhen, applyWhenValue, createMetadataKey, customError, emailError, form, listMetadataKey, maxError, maxLengthError, maxMetadataKey, minError, minLengthError, minMetadataKey, orMetadataKey, patternError, provideSignalFormsConfig, reducedMetadataKey, requiredError, schema, standardSchemaError, submit };
2268
- export type { AsyncValidationResult, ChildFieldContext, CompatFieldState, CompatSchemaPath, Debouncer, DisabledReason, FieldContext, FieldState, FieldTree, FieldValidator, FormOptions, ItemFieldContext, ItemType, LogicFn, MaybeFieldTree, MaybeSchemaPathTree, OneOrMany, ReadonlyArrayLike, RootFieldContext, Schema, SchemaFn, SchemaOrSchemaFn, SchemaPath, SchemaPathTree, SignalFormsConfig, Subfields, SubmittedStatus, TreeValidationResult, TreeValidator, ValidationResult, ValidationSuccess, Validator, WithField, WithOptionalField, WithoutField };
2347
+ export { CustomValidationError, EmailValidationError, FIELD, Field, MAX, MAX_LENGTH, MIN, MIN_LENGTH, MaxLengthValidationError, MaxValidationError, MetadataKey, MetadataReducer, MinLengthValidationError, MinValidationError, NgValidationError, PATTERN, PathKind, PatternValidationError, REQUIRED, RequiredValidationError, SchemaPathRules, StandardSchemaValidationError, ValidationError, apply, applyEach, applyWhen, applyWhenValue, createManagedMetadataKey, createMetadataKey, customError, emailError, form, maxError, maxLengthError, metadata, minError, minLengthError, patternError, provideSignalFormsConfig, requiredError, schema, standardSchemaError, submit };
2348
+ export type { AsyncValidationResult, ChildFieldContext, CompatFieldState, CompatSchemaPath, Debouncer, DisabledReason, FieldContext, FieldState, FieldTree, FieldValidator, FormOptions, ItemFieldContext, ItemType, LogicFn, MaybeFieldTree, MaybeSchemaPathTree, MetadataSetterType, OneOrMany, ReadonlyArrayLike, RootFieldContext, Schema, SchemaFn, SchemaOrSchemaFn, SchemaPath, SchemaPathTree, SignalFormsConfig, Subfields, SubmittedStatus, TreeValidationResult, TreeValidator, ValidationResult, ValidationSuccess, Validator, WithField, WithOptionalField, WithoutField };