title: Assign class instance property a value based on its type in Typescript Angular
body: <p>I don't know if this is allowed in Typescript, but I'm working in an Angular 7 project and I want to instantiate a <code>Page</code> class fullfilling all his properties from DB object. These are my classes:</p>
  
  <pre><code>export class User {
      id: number;
      name: string;
      created_at: string;
  
      constructor(obj?: any) {
          Object.assign(this, obj);
      }
  
      getName(): string {
          return this.name;
      }
  }
  
  export class Page {
      id: number;
      title: string;
      author: User;
  
  
      constructor(obj?: any) {
          Object.assign(this, obj);
      }
  
      showTitle(): string {
          return this.title;
      }
  }
  </code></pre>
  
  <p>Here is an example of my service method to retrieve the data:</p>
  
  <pre><code>import { HttpClient } from '@angular/common/http';
  import { Injectable } from '@angular/core';
  
  import { Observable } from 'rxjs';
  import { map } from 'rxjs/operators';
  
  import { Page } from '../models/page';
  
  @Injectable()
  export class PageService {
  
      constructor(httpClient: HttpClient) {}
  
      getPage(id: number): Observable&lt;Page&gt; {
          return this.httpClient
                     .get&lt;Page&gt;('http://&lt;my-server-ip&gt;:&lt;port&gt;/api/pages')
                     .pipe(
                         map((page: Page) =&gt; {
                             console.log('retrieved', page);
                             return new Page(page);
                         })
                     );
      }
  }
  </code></pre>
  
  <p>And here is an example of this function call in my component</p>
  
  <pre><code>export class MyCustomComponent implements OnInit {
  
      constructor(pageService: PageService) {}
  
      ngOnInit() {
          this.pageService.getPage()
              .subscribe((page: Page) =&gt; {
                  console.log(page.showTitle());
              });
      }
  }
  </code></pre>
  
  <p>This example works, but when I want to access to <code>User</code> methods, like:</p>
  
  <pre><code>console.log(page.author.getName());
  </code></pre>
  
  <p>I don't have access to them because it is not an instantiation of <code>User</code> class.</p>
  
  <p>The same would happen with <code>Page</code> if I do not return a new instance of page class as an observable, thats why I use <code>return new Page(page)</code> after retrieving the data.</p>
  
  <p>The problem is that I want to keep my constructors as generic as possible, so creating a constructor to assign the value manually (e.g.: <code>this.author = new User(obj.author);</code>) is not a valid workaround, as I want to implement it in every model or create a <code>GenericModel</code> then extend all my models.</p>
  
  <p>Is there a way to fill a property with defined type in a instantiated class depending in its type?</p>
  
  <p>This is what I tried so far, but it doesn't work:</p>
  
  <pre><code>export class Page {
      // ...
      constructor(obj?: any) {
          Object.keys(obj).forEach((key: string, index: number) =&gt; {
              if (typeof(obj[key]) === 'object' &amp;&amp; obj[key] !== null) {
                  this[key] = new (this[key].constructor)(obj[key]);
              } else {
                  this[key] = obj[key]
              }
          });
      }
  }
  </code></pre>
  
  <pre><code>ERROR TypeError: Cannot read property 'author' of null
  ERROR TypeError: Cannot read property 'constructor' of undefined
  </code></pre>
  
  <p>I understand that <code>this</code> is null when constructor is called, but I couldn't find another way to fill <code>author</code> property with a <code>new</code> instance to access to methods. Also, if I get a standard/default object like <code>{ ... }</code>, the <code>if</code> will trigger and probably will throw an error too, as it does not have a constructor.</p>