title: Generic TypeScript interface with mixed member types
body: <p>For several HTML forms, I want to configure inputs and deal with their values. My types have the following structure (you may copy it to TypeScript Playground <a href="http://www.typescriptlang.org/play" rel="nofollow noreferrer">http://www.typescriptlang.org/play</a> to see it in action):</p>
  
  <pre><code>interface InputConfig {
      readonly inputType: "text" | "password" | "list"
      readonly attributes?: ReadonlyArray&lt;string&gt;
      readonly cssClasses?: ReadonlyArray&lt;string&gt;
  }
  
  interface Inputs&lt;T extends InputConfig | string | string[]&gt; {
      readonly username: (T &amp; InputConfig) | (T &amp; string)
      readonly password: (T &amp; InputConfig) | (T &amp; string)
      readonly passwordConfirmation: (T &amp; InputConfig) | (T &amp; string)
      readonly firstname: (T &amp; InputConfig) | (T &amp; string)
      readonly lastname: (T &amp; InputConfig) | (T &amp; string)
      readonly hobbies: (T &amp; InputConfig) | (T &amp; string[])
  }
  
  type InputConfigs = Inputs&lt;InputConfig&gt; // case 1 (see below)
  type InputValues = Inputs&lt;string | string[]&gt; // case 2 (see below)
  
  const configs: InputConfigs = {
      username: {
          inputType: "text"
      },
      password: {
          inputType: "password"
      },
      passwordConfirmation: {
          inputType: "password"
      },
      firstname: {
          inputType: "text"
      },
      lastname: {
          inputType: "text"
      },
      hobbies: {
          inputType: "list"
      }
  }
  
  const values: InputValues = {
      username: "testuser1",
      password: "test1",
      passwordConfirmation: "test1",
      firstname: "Tester",
      lastname: "1",
      hobbies: ["a", "b", "c"]
  }
  
  const username: string = values.username
  </code></pre>
  
  <p>The most important advantage of this generic approach is the single point of field naming in the <code>Inputs</code> interface: The names <code>username</code>, <code>password</code>, <code>passwordConfirmation</code>,... are used by <strong>both</strong> <code>InputConfigs</code> <strong>and</strong> <code>InputValues</code> which makes renaming as easy as possible.</p>
  
  <p><strong>Unfortunately, it does not work as expected since the last assignment <code>const username: string = values.username</code> is not accepted by the compiler:</strong></p>
  
  <pre><code>Type 'string | (string &amp; InputConfig) | (string[] &amp; InputConfig) | (string[] &amp; string)' is not assignable to type 'string'.
    Type 'string[] &amp; InputConfig' is not assignable to type 'string'.
  </code></pre>
  
  <p>I expected it to work because my understanding was:</p>
  
  <ul>
  <li>case 1: <code>T</code> is <code>InputConfig</code> and thus <code>username</code> is of type <code>InputConfig</code> because:
  
  <ul>
  <li><code>T &amp; InputConfig</code> = <code>InputConfig &amp; InputConfig</code> = <code>InputConfig</code></li>
  <li><code>T &amp; string</code> = <code>InputConfig &amp; string</code> = nothing</li>
  </ul></li>
  <li>case 2: <code>T</code> is <code>string | string[]</code> and thus <code>username</code> is of type <code>string</code> because:
  
  <ul>
  <li><code>T &amp; InputConfig</code> = <code>(string | string[]) &amp; InputConfig</code> = nothing</li>
  <li><code>T &amp; string</code> = <code>(string | string[]) &amp; string</code> = <code>string</code></li>
  </ul></li>
  </ul>