title: How can I use a string enum type as a computed property name in an interface?
body: <p>I am modeling an API request format in TypeScript:</p>
  
  <pre><code>interface ApiTerm {
      term: {
          name: string,
          value: string,
      }
  }
  
  interface ApiAnd {
      and: {
          lhs: ApiItem,
          rhs: ApiItem,
      }
  }
  
  interface ApiOr {
      or: {
          lhs: ApiItem,
          rhs: ApiItem,
      }
  }
  
  type ApiItem =
      | ApiTerm
      | ApiAnd
      | ApiOr
      ;
  </code></pre>
  
  <p>This works, but I will need to implement many binary operations beyond just "and" and "or" so I'd like some way to shorten and reuse the code. </p>
  
  <p>Following some other code I've written that uses a specific string enum <em>value</em> in an interface, I tried to use a string enum as the property name:</p>
  
  <pre><code>enum Operation {
      And = "and",
      Or = "or",
  }
  
  interface ApiBinary&lt;O extends Operation&gt; {
      [O]: {
          lhs: ApiItem,
          rhs: ApiItem,
      }
  }
  
  type ApiItem =
      | ApiTerm
      | ApiBinary&lt;Operation.And&gt;
      | ApiBinary&lt;Operation.Or&gt;
      ;
  </code></pre>
  
  <p>Unfortunately, this generates an error with TypeScript 2.9.1:</p>
  
  <pre class="lang-none prettyprint-override"><code>A computed property name in an interface must refer to an expression whose type is a literal type or a 'unique symbol' type.
  </code></pre>
  
  <p>Is there an alternative solution that will allow me to avoid having to write out the numerous duplicate interfaces that will only differ by the name of the key?</p>
  
  <p>Looking into the "a 'unique symbol' type" part of the error message, I don't believe I can create an enum based on <code>Symbol</code>s.</p>
  
  <h3>Related questions</h3>
  
  <p><a href="https://stackoverflow.com/q/46822063/155423">Use string enum value in TypeScript interface as a computed property key</a> seems very close, but is about using specific string enum values in an interface, which works as-in in newer TypeScript versions.</p>