title: Typescript: Force a deep partial assigned property to have the right type
body: <p>I have created a <code>DeepPartial</code> type in Typescript:</p>
  <pre><code>type DeepPartial&lt;T&gt; = {
      [P in keyof T]?: DeepPartial&lt;T[P]&gt;;
  };
  </code></pre>
  <p>And use this functionality to assign data to an object. So far so good!</p>
  <pre><code>class Order {
     constructor(obj: DeepPartial&lt;Order&gt;) {
      Object.assign(this, obj);
    }
    id: string = '';
    lines: OrderLine[] = [];
  
    getInfo() {
      return 'Order ID:'+this.id;
    }
  }
  
  const order = new Order({id:'982734'});
  console.log(order.getInfo()); // OK (Order ID:982734&quot;)
  </code></pre>
  <p>But now I also would like to assign order lines to this object. The <code>OrderLine</code> itself looks like this:</p>
  <pre><code>class OrderLine {
     constructor(obj: DeepPartial&lt;OrderLine&gt;) {
      Object.assign(this, obj);
    }
    product: string = '';
  
    getInfo() {
      return 'Product name:'+this.product;
    }
  }
  </code></pre>
  <p>The partial copy itself looks fine, because I'm able to access the products:</p>
  <pre><code>const order = new Order({
    id:'982734',
    lines: [
      {product:'pizza'},
      {product:'cheese'}
    ]
  });
  console.log(order.getInfo()); // OK (Order ID:982734&quot;)
  
  order.lines.forEach(line =&gt; {
    console.log(line.product); // OK (pizza + cheese)
  })
  </code></pre>
  <p>But when I try to access the <code>getInfo()</code> on the <code>OrderLine</code> I see the error message &quot;(line.getInfo is not a function)&quot;</p>
  <pre><code>order.lines.forEach(line =&gt; {
    console.log(line.getInfo()); // NOK (line.getInfo is not a function)
  })
  </code></pre>
  <p>It looks like the issue is that <code>order.lines</code> is not an instance of <code>OrderLine</code>, but how can I fix this with a deep partial copy without casting order.lines explicitly? <a href="https://www.typescriptlang.org/play?ssl=43&amp;ssc=3&amp;pln=41&amp;pc=1#code/C4TwDgpgBAIhFgAoEMBOwCWyA2AeAKgHxQC8UA3gFBQ1QDaiUGAdlANYQgD2AZlPgF0A-AC5Y8JGkw4CDAYQDclAL5LKAY2zIAztqgB5VABMIqCtRrquzbcFQBXdcC6oAFFwBGAKzFwEKdCw8QxNUQgBKc1oDbwgnADodbQwAc2ZXYAALDG0AGihPL3ClGmULDCMxW1QWFNIoAHIGkqhsFghtMRDTABl2ugF6gbUaFIhgAElmHi5XSKpo1HH7VFYG7rMJmBEGgGosnPiKlrKyjS1dA2Ne9qjLa2rHZzdC3wkA6WDr1D7mCAi7jR9LEEklUukDnkCt5ihYyjQwKguEYnlU7LV6k0RlAxpNprN5hYaEtgCs1ogkSinFBmMgALYQHb7bLaeKI5FPE4qSgaB7AArfep-ADuV1CrgWTEqDQAnAAOABMAHYAMwAFgauQsbT%20nXoRIo7KpwB2YAwAC9zcgGsotdFyEbUQ11Jl4NoIDaLAIVLCrDYuNgIPFsFwUu5vvFcVMZnNilAAPTxgwAaSgrg2UC2InlyvVACJwjyXKFg%201WTNUABRZAu1w66AkYiSv3aANBkNh%20tsylPOOJlNps2W5BQXZQF1uiCF5SFyjF0yl3XxCvV2v10hNiwttvB0N19qR8bRgl9pMAOX0qf3f0PeJmTD0zC4-JHPHszCcGGs08LQA" rel="nofollow noreferrer">Example code</a></p>