angular / angular/angular

Add typed key for `FormRecord`

Abierto
#49,442 1 comentario 4 reacciones 0 asignados Ver en GitHub
area: forms
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

Abrir la 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

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.