title: TypeScript Type Merging
body: <p>I have a case where I want to "merge" types where the default type joining (i.e. <code>T | U</code> or <code>T &amp; U</code>) doesn't achieve what I want.</p>
  
  <p>What I am trying to make is a deep and smart type merge that will automatically mark properties as optional during the merge and perform deep merges of TypeScript interfaces/types.</p>
  
  <p>To give an example, assume we have types <code>A</code> and <code>B</code>.</p>
  
  <pre class="lang-js prettyprint-override"><code>type A = {
    a: string;
    b: number;
    c: boolean;
    d: {
      a2: string;
      b2: number;
    };
    e?: number;
  };
  
  type B = {
    a: string;
    b: boolean;
    d: {
      a2: string;
      c2: boolean;
    };
  };
  </code></pre>
  
  <p>I am looking for a <code>Merge</code> function that would accept 2 generic types</p>
  
  <pre class="lang-js prettyprint-override"><code>type Merge&lt;T, U&gt; = ?????;
  </code></pre>
  
  <p>Then, if used on types <code>A</code> and <code>B</code>, the output would be as follows</p>
  
  <pre><code>type AB = {
    a: string;
    b: number | boolean;
    c?: boolean;
    d: {
      a2: string;
      b2?: number;
      c2?: boolean;
    };
    e?: number;
  };
  </code></pre>
  
  <p>As this shows, the <code>Merge</code> type would perform the following logic:</p>
  
  <ol>
  <li>If the property exists on both <code>T</code> and <code>U</code> and is an identical type, mark it as required and be set to the type in both <code>T</code>/<code>U</code> (like what occurred with property <code>a</code>).</li>
  <li>If the property exists on both <code>T</code> and <code>U</code> but is a different type, mark it as required and set to a union type if it is a primitive (like what occurred with property <code>b</code>) or do a recursive merge if it is an object (like what occurred with property <code>d</code>).</li>
  <li>If the property exists on one type but not another, mark the property as optional and set it to the type that it was in the input type where it actually existed (like what occurred with property <code>c</code> as well as <code>b2</code> and <code>c2</code>).</li>
  <li>If the property is already optional in one type, it should be optional on the output type with the existing rules above applied for determining its value (like what occurred with property <code>e</code>)</li>
  </ol>
  
  <p>Assume that you can use recursive conditional types although I recognize that they <a href="https://github.com/Microsoft/TypeScript/issues/26980" rel="noreferrer">aren't yet officially supported</a> and should not be used in production. I can make an unrolled version similar to jcalz@'s solution <a href="https://stackoverflow.com/a/58986589/7229391">here</a> for production use cases.</p>
  
  <p><a href="https://www.typescriptlang.org/play#code/C4TwDgpgBAglC8UDeAoKUCGAuKBnYATgJYB2A5gNxpQBGOJArgLY0QFXoDGONA9rwBsIGEhygATHKnToMAJhz5i5MehoKojFmzEBfMRAD89Zq3Yp9KFKEhQAQgmTVseQqUrU6tfkJFjJTjIy8opuKtRBnBp8gsKi1JaW1uDQALJsZBAAPAAqADRQAKoAfI6G5eVUybYwDojpBJlZMAV2xVQA9ABUXWhdUADKABa8DALiUBAAjgwYAlDAQ0S4WH1QazbQtY7S-bKhyh5Qe7Qm2gRQAD7esX5rXMY3vvHHMgG7QZgaSu4cJ2pyR5aMx-T5RR4xZ6g9CWV7oIxnEFrWFdDpAA" rel="noreferrer">Here is a playground</a> set up for the question to test with.</p>