title: TypeScript convert object from type with optional property to type without optional property
body: <p>I'm new to TypeScript and I am facing a pretty trivial problem. I am using a third party email library that I wrap in a service function that I control. The third party function as well as my service function accept an object with common email configuration properties (to, from, subject, body ...), but the third party function requires all of these while my service lets the from property be optional. See below.</p>
  
  <pre><code>// Third Party Code
  
  type ThirdPartyEmailData = {
    from: string;
    to: string;
    subject: string;
    body: string;
  }
  
  const sendEmailWithThirdPartyService = (emailData: ThirdPartyEmailData) =&gt; {
  
    console.log('Sending email from:', emailData);
  
  }
  
  -----------------------------------------------------------------------------
  
  // My Code
  
  type MyEmailData = {
    from?: string;
    to: string;
    subject: string;
    body: string;
  }
  
  const sendEmail = (emailData: MyEmailData) =&gt; {
  
    emailData = { from: 'info@company.com', ...emailData };
  
    sendEmailWithThirdPartyService(emailData); // This does not compile
  
    /**
     * Argument of type 'MyEmailData' is not assignable to parameter of type 'ThirdPartyEmailData'.
     * Property 'from' is optional in type 'MyEmailData' but required in type 'ThirdPartyEmailData'.
     */
  
  }
  
  sendEmail({
    to: 'john.doe@customer.com',
    subject: 'I &lt;3 TypeScript',
    body: 'But TypeScript hates me'
  });
  </code></pre>
  
  <p>As expected, the above does not compile because the type 'MyEmailData' is not assignable to parameter of type 'ThirdPartyEmailData'. I have been looking for a clean way to convert/change/cast the type of emailData before I pass it to the third party function, but I can'r really find a good way. Below are a few things I came up with, but it does not feel good.</p>
  
  <p><strong>Solution 1: just cast to the third party type</strong></p>
  
  <pre><code>// My Code
  
  const sendEmail = (emailData: MyEmailData) =&gt; {
  
    // If you remove the line below the program still compiles but breaks at runtime
    emailData = { from: 'info@company.com', ...emailData };
  
    sendEmailWithThirdPartyService(&lt;ThirdPartyEmailData&gt;emailData); // This compiles
  
  }
  </code></pre>
  
  <p><strong>Solution 2: use a type guard to ensure the from property is present</strong></p>
  
  <pre><code>// My Code
  
  const sendEmail = (emailData: MyEmailData) =&gt; {
  
    emailData = { from: 'info@company.com', ...emailData };
  
    // By using the type guard, we ensure that the type of emailData overlaps ThirdPartyEmailData
    if (! hasFromProperty(emailData)) throw new Error('From property is missing');
  
    sendEmailWithThirdPartyService(emailData); // This compiles
  
  }
  
  -----------------------------------------------------------------------------
  
  // Utilities
  
  /** Utility to make certain keys of a type required */
  type RequiredKeys&lt;T, K extends keyof T&gt; = Exclude&lt;T, K&gt; &amp; Required&lt;Pick&lt;T, K&gt;&gt;
  
  /** Typeguard for property 'from' in MyEmailData */
  const hasFromProperty = (data: MyEmailData): data is RequiredKeys&lt;MyEmailData, 'from'&gt; =&gt; {
  
    return 'from' in data;
  
  }
  </code></pre>
  
  <p>This looks like a very common problem, yet I have not been able to find a satisfying solution. What can you recommend ?</p>