#New to generic types, wondering if I'm close to getting this mapping to work

1 messages · Page 1 of 1 (latest)

edgy compass
#

I've been working with Typescript and Angular for 4ish years and I've never used generic types. I've kind of jumped into the deep-end and I've learned a bunch so far. But I'm wondering if I'm close at all to getting this mapping to work. https://stackblitz.com/edit/stackblitz-starters-y7sxis?file=my-attempt.ts

While this is Angular, I don't think any angular knowledge is required to really understand what's going on except that FormArray, FormControl and FormGroup all extend AbstractControl.

I'm kind of at the end of the rope, as I'm finding it hard to locate the right documentation I need to get this to work. If I'm not even close, I'm happy to abandon this, as it was mostly just an attempt to learn. Any help is appreciated, Thanks!

An angular-cli project based on @angular/animations, @angular/common, @angular/compiler, @angular/core, @angular/forms, @angular/platform-browser, @angular/platform-browser-dynamic, @angular/router, core-js, rxjs, tslib and zone.js

rough citrus
#

your mapped type seems to be incorrect around its handling of arrays

#

I don't know any angular whatsoever, but from playing with your code, the first error in the document is complaining about a missing FormGroup

#
  phoneNumbers: string[];
  orderHistory: Order[];

are both arrays

#

your mapping rule

Type[Prop] extends (infer U)[] ? FormArray<TestOne<U>> : {snip}
#

tells typescript to replace every array type with a FormArray<TestOne<U>> which works for visits and phoneNumber because you're populating them with the correct objects

#

but you expect orderHistory: Order[] to transform into FormArray<FormGroup<TestOne<U>>>

rough citrus
#
type TestOne<Type> = 
  Type extends Date
    ? FormControl<Date>
    : Type extends object
      ? FormGroup<{
        [Prop in keyof Type]: 
          Type[Prop] extends (infer U)[]
            ? FormArray<TestOne<U>>
            : Type[Prop] extends Date
              ? FormControl<Date>
              : Type[Prop] extends object
                ? TestOne<Type[Prop]>
                : FormControl<Type[Prop]>;
      }>
      : FormControl<Type>;

I think this is a more accurate type, judging by the jsdoc/errors

#

I then remove all of the <> annotations from assigning to this.testOne

#

letting typescript infer the appropriate types for the various FormGroups where possible

broken yokeBOT
#
webstrand#0

Preview:```ts
import {
FormArray,
FormControl,
FormGroup,
} from "@angular/forms"

class MyAttempt {
testOne: TestOne<User>
constructor() {
this.testOne = new FormGroup({
visits: new FormArray<FormControl<Date>>([]),
accountCreatedOn: new FormControl(new Date()),
name: new FormControl("", {nonNullable: true}),
age: new FormControl(0, {nonNullable: true}),
phoneNumbers: new FormArray<FormControl<string>>(
[]
...```

rough citrus
#

there's still one error somewhere, you've got a FormControl<Date | null> that's too narrow to be assigned from FormControl<Date | null | undefined>

#

I'm not sure where that issue is coming from, and I'm out of time here.