Add typed key for `FormRecord`
- Lenguaje dominante
- TypeScript
- Estrellas
- 101k
- Forks
- 27.5k
- Merge medio
- 1 d 19 h
- PR fusionados (30 d)
- 288
Descripción
### Which @angular/* package(s) are relevant/related to the feature request?
forms
### Description
Currently, the `FormRecord` only support typing the control, but not the key:
```ts
new FormRecord>({
key1: new FormControl(false, { nonNullable: true }),
key2: new FormControl(false, { nonNullable: true }),
key3: new FormControl(false, { nonNullable: true }),
});
```
Here the controls can only be `FormControl` but the keys of the controls can be anything (as long as it is a string).
But in some cases we want to key to be restricted to a specific set of strings (or Enum).
```ts
enum ControlKey {
Key1 = 'key1',
Key2 = 'key2',
Key3 = 'key3',
}
new FormRecord>({
key1: new FormControl(false, { nonNullable: true }),
key2: new FormControl(false, { nonNullable: true }),
key4: new FormControl(false, { nonNullable: true }), // I want the "key4" to throw a typing error here
});
```
This would be useful for known list of options that we can active/deactivate through a form.
The topic has already been discussed here:
- https://github.com/angular/angular/pull/45607#issuecomment-1098292360
- https://github.com/angular/angular/discussions/44513#discussioncomment-1991963
But it looks like it has never been considered as a new feature.
### Proposed solution
We could update the typing of `FormRecord` with something like this:
```ts
export class FormRecord<
TControl extends AbstractControl = AbstractControl,
TKey extends string = string
> extends FormGroup>> {}
export interface FormRecord {
registerControl(name: TKey, control: TControl): TControl;
addControl(name: TKey, control: TControl, options?: { emitEvent?: boolean }): void;
removeControl(name: TKey, options?: { emitEvent?: boolean }): void;
setControl(name: TKey, control: TControl, options?: { emitEvent?: boolean }): void;
contains(controlName: TKey): boolean;
setValue(value: Partial>>, options?: { onlySelf?: boolean, emitEvent?: boolean }): void;
patchValue(value: Partial>>, options?: { onlySelf?: boolean, emitEvent?: boolean }): void;
reset(value?: Partial>>, options?: { onlySelf?: boolean, emitEvent?: boolean }): void;
getRawValue(): Partial>>;
}
```
So that we can use it like this:
```ts
enum ControlKey {
Key1 = 'key1',
Key2 = 'key2',
Key3 = 'key3',
}
const form = new FormRecord, ControlKey>({
[ControlKey.Key1]: new FormControl(false, { nonNullable: true }),
[ControlKey.Key2]: new FormControl(false, { nonNullable: true }),
[ControlKey.Key3]: new FormControl(false, { nonNullable: true }),
});
```
### Alternatives considered
At the moment I'm using a `FormGroup` to match my need:
```ts
enum ControlKey {
Key1 = 'key1',
Key2 = 'key2',
Key3 = 'key3',
}
new FormGroup>>>({
[ControlKey.Key1]: new FormControl(false, { nonNullable: true }),
[ControlKey.Key2]: new FormControl(false, { nonNullable: true }),
[ControlKey.Key3]: new FormControl(false, { nonNullable: true }),
});
```
Guía de contribución
Línea de trabajo
Comienza en el paquete @angular/forms localizando el tipo FormRecord y sus APIs de gestión de controles y valores. Revisa el pull request vinculado y el debate sobre las restricciones anteriores; después, verifica que las claves tipadas se hagan cumplir durante la construcción y en los métodos con nombre, mientras que el uso existente de claves de tipo string siga siendo compatible.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- angular, typescript
- Área
- frontend
- Tipo de issue
- Nueva funcionalidad
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Estado de actividad
- Estancado
- Claridad
- Bien especificado
- Aptitud para principiantes
- 45/100