title: How to provide default value for union type parameter without getting "could be instantiated with a different subtype of constraint"
body: <p>As a follow-up to <a href="https://stackoverflow.com/questions/58533379/how-to-get-function-to-narrow-return-value-type-to-specific-subtype-instead-of-r/58533650#58533650">my previous question</a>...</p>
  
  <p>Is there a way to provide a default value for <code>valueProp</code> in the following example?</p>
  
  <pre><code>type ValueType = 'value' | 'defaultValue'
  
  type Props&lt;T extends ValueType&gt; =
    Record&lt;T, string&gt; 
    &amp; { other: string }
  
  function props&lt;T extends ValueType&gt;(valueProp: T): Props&lt;T&gt; {
    return {
      [valueProp]: 'value',
      other: 'other',
    } as Props&lt;T&gt;
  }
  
  let { defaultValue, other } = props('defaultValue') // ok
  let { value } = props('value') // ok
  </code></pre>
  
  <p><a href="https://www.typescriptlang.org/play/#code/C4TwDgpgBAaghgGwK4QCrmgXigcgG6Io5QA+uAJhAGZxILDzIQ4BQLokUACgE4D2YAM4AeVFAgAPYBAB25QbEJoMAPiiYWUKACUIAYz49yogDRRBwHgEsZAczWaoAMigBvKH2AALCDwBc5pY2tlAAvmxUSDJ6wFZ8MlBg-EKi4lKy8opM6JAqABQETLwCAagAlAHFKahqro48EMBIPAl1WloA2oUoVQC6AfhKOCaOWp4+-rjjvsOOoVBwClUiNSzhLAD0G1CoEBaCLAiNblCUNHQMSmbTPGHqicmCeThntPSMRGVQWx4A1ofHdzdaDzbBJARPQZMHBfH58f4sSLRWLxNKQGKCAAi1DelyYeVcrwuHwg128vlClUewheOOJQxUXzaUAMMkEfCOADoEHxbM8ie8lH5hqc6YKmGU1ixJOjgFixXiUHlwUJ+QqSTDYdt4dKJLL5edxUqVZDgZrvttfPweGZFmj9NJyEA" rel="nofollow noreferrer">Play</a></p>
  
  <hr>
  
  <p>When I try this:</p>
  
  <pre><code>function props&lt;T extends ValueType&gt;(valueProp: T = 'value'): Props&lt;T&gt; {
    return {
      [valueProp]: 'value',
      other: 'other',
    } as Props&lt;T&gt;
  }
  </code></pre>
  
  <p>, I get this error:</p>
  
  <pre><code>Type '"value"' is not assignable to type 'T'.
    '"value"' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'ValueType'.
  </code></pre>
  
  <p>I understand this error (<a href="https://stackoverflow.com/questions/56505560/could-be-instantiated-with-a-different-subtype-of-constraint-object/56701587#56701587">1</a>, <a href="https://github.com/Microsoft/TypeScript/issues/29049" rel="nofollow noreferrer">2</a>, <a href="https://github.com/microsoft/TypeScript/issues/29397#issuecomment-453864746" rel="nofollow noreferrer">3</a>, <a href="https://github.com/microsoft/TypeScript/issues/33436#issuecomment-531738967" rel="nofollow noreferrer">4</a>) in general, but still don't always know the best way to <em>resolve</em> this error.</p>
  
  <p>Is there an easy way to do what I'm trying to do?</p>
  
  <p>It just seems like there ought be an easy way to provide a default value, but maybe default values just don't mix so well with generic type constraints?</p>
  
  <h2>Default type for the generic type?</h2>
  
  <p>I tried this:</p>
  
  <pre><code>function props&lt;T extends ValueType = 'value'&gt;(valueProp: T = 'value'): Props&lt;T&gt; {
    return {
      [valueProp]: 'value',
      other: 'other',
    } as Props&lt;T&gt;
  }
  </code></pre>
  
  <p>but of course got the same error, because T could still be <code>defaultValue</code> if a specific <code>T</code> is provided:</p>
  
  <pre><code>props&lt;'defaultValue'&gt;()
  </code></pre>
  
  <h2>Type assertions?</h2>
  
  <p>I thought of doing this, which compiles, but still doesn't prevent <code>valueProp</code> from disagreeing with T:</p>
  
  <pre><code>function props&lt;T extends ValueType&gt;(valueProp: T = 'value' as T): Props&lt;T&gt; {
    return {
      [valueProp]: 'value',
      other: 'other',
    } as Props&lt;T&gt;
  }
  
  console.log(props&lt;'defaultValue'&gt;())
  // =&gt; {value: "value", other: "other"}
  </code></pre>
  
  <h2>Something more complicated?</h2>
  
  <p>I'm still hoping there's a simple solution, but if not, maybe something more complicated would work?</p>
  
  <p>Maybe using a mapping table that maps from a <em>type</em> to the default <em>value</em> for that type?</p>
  
  <p>For inspiration, maybe something kind of like:</p>
  
  <ul>
  <li><p><a href="https://stackoverflow.com/questions/57363278/customenum-case-is-assignable-to-the-constraint-of-type-t-but-t-could-be/57366095#57366095">&#39;CustomEnum.Case&#39; is assignable to the constraint of type &#39;T&#39;, but &#39;T&#39; could be instantiated with a different subtype of constraint &#39;CustomEnum&#39;</a>
  or</p></li>
  <li><p><a href="https://github.com/microsoft/TypeScript/issues/29528#issuecomment-456804257" rel="nofollow noreferrer">https://github.com/microsoft/TypeScript/issues/29528#issuecomment-456804257</a>
  ?</p></li>
  </ul>