title: User-Defined Type Guard Results in Intersection Type
body: <p>I'm playing around with Typescript and was trying to see if I could create the concept of an <code>Either</code> type to represent success and failure paths. I've created a user-defined type guard to explicitly narrow the types of success/failure through the use of a Symbol. I can't figure out why the value of <code>either</code> in the isFailure branch is shown as being the intersection type of <code>Data &amp; CustomError</code> as opposed to just <code>CustomError</code>.</p>
  
  <pre><code>const FailureSymbol = Symbol('Failure');
  
  interface IFailure {
      symbol: Symbol;
  }
  
  type Success&lt;T&gt; = T
  type Failure&lt;T extends IFailure&gt; = T
  
  type Either&lt;T, U extends IFailure&gt; = Success&lt;T&gt; | Failure&lt;U&gt;
  
  function isFailure&lt;T, U extends IFailure&gt;(either: Either&lt;T, U&gt;): either is Failure&lt;U&gt; {
      const candidateFailure = either as Failure&lt;U&gt;;
      return candidateFailure.symbol &amp;&amp; candidateFailure.symbol === FailureSymbol;
  }
  
  interface Data {
      data: string;
  }
  
  interface CustomFailure {
      symbol: Symbol;
      errorMessage: string;
  }
  
  let either: Either&lt;Data, CustomFailure&gt; = { data: 'success' }; 
  
  if (isFailure&lt;Data, CustomFailure&gt;(either)) {
      // inside this branch the type of either is shown to be: Data &amp; CustomFailure
      console.log('failure', either);
  } else {
      // inside this branch the type of either is show to be: Data
      console.log('success', either)
  }
  </code></pre>