Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
wants to merge 1 commit into from

Conversation

Toxicable
Copy link

@Toxicable Toxicable commented Oct 30, 2017

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

@Trophalaxeur
Copy link

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
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
Copy link

c69 commented Dec 12, 2017

@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
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
Contributor

Nice work 👏

@ironstine
Copy link

Nice one @Toxicable!

@indrek-rajamets
Copy link

Nice work, any hope on merging this soon?

@ngbot
Copy link

ngbot bot commented Jan 30, 2018

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
Copy link

ngbot bot commented Jan 30, 2018

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 Issue that requests a new feature label Sep 18, 2018
@ghost
Copy link

ghost commented Nov 9, 2018

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

@hisham
Copy link

hisham commented Nov 9, 2018

+1

@dannyskoog
Copy link
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

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
Contributor

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

@dvitiuk-opensource
Copy link

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

@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
Copy link

kbrilla commented Aug 23, 2019

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
Contributor

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

Why is that a blocker?

@FrancescoBorzi
Copy link

@kara are there any news about this?

@Wilt
Copy link

Wilt commented Jun 3, 2020

Possibly good news here...

#13721 (comment)

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

@AndrewKushnir
Copy link
Contributor

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

@angular-automatic-lock-bot
Copy link

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 Issue that requests a new feature jira-sync
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Reactive forms are not strongly typed