title: Typescript type annotations for generics with constraints
body: <p>I have a curried function with generics that I don’t know how to use without losing precise type information. I am able to use it by specifying a concrete type, but then I cannot use it in another context. I am able to use it with a minimal type, but then typescript loses information about the function output.</p>
  <pre class="lang-js prettyprint-override"><code>/* eslint-disable @typescript-eslint/no-unused-vars */
  const filterBy = &lt;T&gt;(check: (x: T) =&gt; boolean) =&gt; (arr: T[]): T[] =&gt; {
    return arr.filter(check)
  }
  
  interface SpecializedTypeWithIdAndMore {
    id: string
    anotherField: string
  }
  
  const items: SpecializedTypeWithIdAndMore[] = [
    /* ... */
  ]
  
  // This is working but can only be applied to SpecializedTypeWithIdAndMore
  const grouperSpecialized = filterBy&lt;SpecializedTypeWithIdAndMore&gt;(
    x =&gt; x.id === 'something',
  )
  const groupedItemsSpecialized = grouperSpecialized(items)
  // groupedItemsSpecialized is SpecializedTypeWithIdAndMore[]
  
  // This is working, but information about the input type is lost
  const grouperTypeLost = filterBy&lt;{ id: string }&gt;(x =&gt; x.id === 'something')
  const groupedItemsTypeLost = grouperTypeLost(items)
  // groupedItemsTypeLost is { id: string }[]
  
  // I would like to write something like this, but it does not work
  const grouperWanted = filterBy&lt;T extends { id: string }&gt;(x =&gt; x.id === 'something')
  const groupedItemsWanted = grouperWanted(items)
  // I would like groupedItemsWanted to be SpecializedTypeWithIdAndMore[]
  </code></pre>