Skip to content

feat(forms): add generic typings to AbstractControl - #20040

Closed
Toxicable wants to merge 1 commit into
angular:masterfrom
Toxicable:abstract-form-control
Closed

feat(forms): add generic typings to AbstractControl#20040
Toxicable wants to merge 1 commit into
angular:masterfrom
Toxicable:abstract-form-control

Conversation

@Toxicable

@Toxicable Toxicable commented Oct 30, 2017

Copy link
Copy Markdown

PR Checklist

Please check if your PR fulfills the following requirements:

  • The commit message follows our guidelines
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)

PR Type

What kind of change does this PR introduce?

[x] Feature

What is the current behavior?

#13721 Currently there is no generic type support for AbstractControl
Therefore AbstractControl#value will always return a value with type: any

What is the new behavior?

Provides type support for AbstractControl#value and related fields/methods

For example:

const control = new FormControl('Toxicable');
const value = control.value;
const changes = control.valueChanges;

In this example control will be control: FormControl<string>
value will be value: string
changes will be changes: Observable<string>

Does this PR introduce a breaking change?

[ ] Yes
[x] No

Duplicate of #16828 since I kinda messed up that branch
closes #13721

@Toxicable
Toxicable force-pushed the abstract-form-control branch 4 times, most recently from e1f0154 to 16a256b Compare October 31, 2017 20:41
@Toxicable
Toxicable force-pushed the abstract-form-control branch 6 times, most recently from f98de13 to 4420bc9 Compare November 1, 2017 06:19
@Trophalaxeur

Copy link
Copy Markdown

Stop me if i'm wrong but,
if i have an object with this interface :

interface MyList {
    name: string[],
    other: number,
}

I need to construct a form like this (without types) :

myform = new FormGroup({
    name: new FormArray([]),
    other: new FormControl(0)
)

If i use typed forms, the property 'name' need to be FormArray
And myform need to be FormGroup
Like,

myform = new FormGroup<MyList>({
    name: new FormArray<string>([]),
    other: new FormControl<number>(0)
)

But, if FormGroup contructor take
controls: {[key in keyof T]: AbstractControl<T[key]>}

Property 'name' will be of type AbstractControl<string[]>. And this is not compatible with FormArray<string>

@Toxicable

Copy link
Copy Markdown
Author

@Trophalaxeur AbstractControl is the base class of all of the other 3 classes.
With FormArray you specify the type of a single item, but the type passed to AbstractControl is an array of that single type as you can see on the signature
FormArray<T = any> extends AbstractControl<T[]>

Therefore AbstractControl<string[]> and FormArray<string> are the same
here's a demo showing this to be true
https://stackblitz.com/edit/angular-gitter-zofzrc?file=app%2Ftyped-controls.ts

@c69

c69 commented Dec 12, 2017

Copy link
Copy Markdown

@Toxicable great job on implementing this.
But i see the PR is stuck at (final) documentation phase - are you accepting extra PRs, and if so maybe i can help ?

@Toxicable

Copy link
Copy Markdown
Author

@c69 untill there is a final API on this there is no need to write docs since the API could change before it lands.

@jotatoledo

Copy link
Copy Markdown
Contributor

Nice work 👏

@Toxicable
Toxicable force-pushed the abstract-form-control branch from 7f4444a to ecc26ae Compare December 29, 2017 20:56
@ironstine

Copy link
Copy Markdown

Nice one @Toxicable!

@indrek-rajamets

Copy link
Copy Markdown

Nice work, any hope on merging this soon?

@ngbot

ngbot Bot commented Jan 30, 2018

Copy link
Copy Markdown

Hi @Toxicable! This PR has merge conflicts due to recent upstream merges.
Please help to unblock it by resolving these conflicts. Thanks!

1 similar comment
@ngbot

ngbot Bot commented Jan 30, 2018

Copy link
Copy Markdown

Hi @Toxicable! This PR has merge conflicts due to recent upstream merges.
Please help to unblock it by resolving these conflicts. Thanks!

@kara kara self-assigned this Aug 22, 2018
@kara kara added the action: review The PR is still awaiting reviews from at least one requested reviewer label Aug 22, 2018
@kara kara added the feature Label used to distinguish feature request from other issues label Sep 18, 2018
@ghost

ghost commented Nov 9, 2018

Copy link
Copy Markdown

I really want this!!!! Can't wait to see this in action!!!!

@hisham

hisham commented Nov 9, 2018

Copy link
Copy Markdown

+1

@dannyskoog

Copy link
Copy Markdown
Contributor

I’m actually surprised that this hasn’t made its way into the framework yet :) Seems like a no-brainer that people want strongly typed functionality these days.

Anyhow - me and my team is waiting eagerly on this one

@maxime1992

Copy link
Copy Markdown

Yes Angular team is aware of that but mentioned during angular Connect 2018 that they are waiting for some TS bug to be fixed 🤷‍♂️

@sarunint

Copy link
Copy Markdown
Contributor

In case you wonder, it's blocked on microsoft/TypeScript#16229.

@dvitiuk-opensource

Copy link
Copy Markdown

Hello!
It is possible to resolve this with current TS version. Rewritten example from microsoft/TypeScript#16229:

class O<T=any> {
  constructor(public array: T[]) { }
}

type Unwrap<T> = T extends O<infer U> ? U : T

declare let val: O<number> | O<string>;
declare function f<V extends O<any>, T=Unwrap<V> >(x: V): T;

const res = f(val); // works

type returnType = typeof res // string | number

f(1); // Argument of type '1' is not assignable to parameter of type 'O<any>'.

playground link

This one also works.

type Unwrap<T> = T extends AbstractControl<infer U> ? U : never

class AbstractControl<T extends any = any> {
  value: T;
}
class FormGroup<T extends any> extends AbstractControl<T> {
  constructor(
    public controls: {[key in keyof T]: AbstractControl<T[key]>}
  ) {
    super()
  }
}
class FormArray<C extends AbstractControl<any> , T = Unwrap<C>> extends AbstractControl<T>{
  constructor(
    public controls: C[]
  ) {
    super()
  }
}
class FormControl<T extends any> extends AbstractControl<T>{
  constructor(value: T) {
    super()
    this.value = value
  }
}


let a = new FormArray([
  new FormGroup({'c2': new FormControl('v2'), 'c3': new FormControl('v3')}),
  new FormArray([new FormControl('v4'), new FormControl(5)])
]);

a.controls[0].value // string | number | { 'c2': string; 'c3': string; }
a.controls[1].value // string | number | { 'c2': string; 'c3': string; }

playground link

I can experiment a bit with typescript tuples to get
a.controls[0].value -> { 'c2': string; 'c3': string; }
and a.controls[1].value -> string | number if needed.

@jasonaden jasonaden added this to the needsTriage milestone Jan 29, 2019
@Lonli-Lokli

Copy link
Copy Markdown

@IgorMinar
what are the priorities in Angular team? More powerful Typescript allows to create more type-safe scenarios, while Angular still focus in Ivy which will answer answer Life, the Universe and Everything question?

@kbrilla

kbrilla commented Aug 23, 2019

Copy link
Copy Markdown
Contributor

Can't we just ask the guys who created https://github.com/no0x9d/ngx-strongly-typed-forms to allow to implement their way of strongly typing into angular? Of course there can be some improvements made thanks to new features of current TS but it is already great implementation with over 1000+ daily downloads on npm.

@kara kara removed their assignment Sep 9, 2019
@pauldraper

Copy link
Copy Markdown
Contributor

In case you wonder, it's blocked on microsoft/TypeScript#16229.

Why is that a blocker?

@FrancescoBorzi

Copy link
Copy Markdown

@kara are there any news about this?

@Wilt

Wilt commented Jun 3, 2020

Copy link
Copy Markdown

Possibly good news here...

#13721 (comment)

I cannot wait for strongly typed forms to be part of Angular.

@AndrewKushnir

Copy link
Copy Markdown
Contributor

Closing this PR in favor of more recent #38406 and #38906. Thank you.

@angular-automatic-lock-bot

Copy link
Copy Markdown

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot Bot locked and limited conversation to collaborators Jan 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

action: review The PR is still awaiting reviews from at least one requested reviewer area: forms cla: yes cross-cutting: types feature Label used to distinguish feature request from other issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reactive forms are not strongly typed