title: Structural typing and user-defined type guards
body: <pre><code>type GraphQLType =
      | GraphQLInt
      | GraphQLList&lt;any&gt;
      | GraphQLNonNull&lt;any&gt;;
  
  interface GraphQLInt {
    int: number
  }
  
  interface GraphQLList&lt;T&gt; {
    x: string
  }
  
  interface GraphQLNonNull&lt;T&gt; {
    x: string
  }
  
  declare function isInt(type: GraphQLType): type is GraphQLInt;
  declare function isList(type: GraphQLType): type is GraphQLList&lt;any&gt;;
  declare function isNonNull(type: GraphQLType): type is GraphQLNonNull&lt;any&gt;;
  
  function doIt(t: GraphQLType) {
    if (isInt(t)) {
      return t.int
    }
  
    if (isList(t)) {
      // t: GraphQLList&lt;any&gt; | GraphQLNonNull&lt;any&gt;
      return t.x
    }
  
    // t: never
  
    if (isNonNull(t)) {
      return t.x
    }
  }
  </code></pre>
  
  <p>The example above causes an error in the isNonNull() block because it determines t to be of type never. In the isList() block t has both types GraphQLList and GraphQLNonNull. Both types are structurally the same. Is this the same problem described <a href="https://github.com/Microsoft/TypeScript/issues/5518" rel="nofollow noreferrer">here</a> and <a href="https://github.com/Microsoft/TypeScript/issues/7271" rel="nofollow noreferrer">here</a> or is it actually a bug?</p>
  
  <p>The reason it should work is because isList() is a type guard for GraphQLList and not GraphQLNonNull, and at runtime it will return true for a List and false for a NonNull, but typescript doesn't seem to be representing the same idea.</p>