title: How can I iterate over Record keys in a proper type-safe way?
body: <p>Let's build an example record over some properties.</p>
  
  <pre><code>type HumanProp = 
      | "weight"
      | "height"
      | "age"
  
  type Human = Record&lt;HumanProp, number&gt;;
  
  const alice: Human = {
      age: 31,
      height: 176,
      weight: 47
  };
  </code></pre>
  
  <p>For each property, I also want add a human-readable label:</p>
  
  <pre><code>const humanPropLabels: Readonly&lt;Record&lt;HumanProp, string&gt;&gt; = {
      weight: "Weight (kg)",
      height: "Height (cm)",
      age: "Age (full years)"
  };
  </code></pre>
  
  <p>Now, using this Record type and defined labels, I want to iterate over two record with the same key types.</p>
  
  <pre><code>function describe(human: Human): string {
      let lines: string[] = [];
      for (const key in human) {
          lines.push(`${humanPropLabels[key]}: ${human[key]}`);
      }
      return lines.join("\n");
  }
  </code></pre>
  
  <p>However, I'm getting an error:</p>
  
  <pre><code>Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Readonly&lt;Record&lt;HumanProp, string&gt;&gt;'.
    No index signature with a parameter of type 'string' was found on type 'Readonly&lt;Record&lt;HumanProp, string&gt;&gt;'.
  </code></pre>
  
  <p>How can I implement this functionality in Typescript properly?</p>
  
  <p>To clarify, the solution I'm looking for, regardless of whether it will use <code>Record</code> type, plain objects, types, classes, interfaces or something else, should have following properties:</p>
  
  <ol>
  <li><p>When I want to define a new property, I only need to do it in one place (like in HumanProp above), and don't repeat myself.</p></li>
  <li><p>After I define a new property, all the places where I should add a new value for this property, like when I'm creating <code>alice</code>, or <code>humanPropLabels</code>, light up <strong>type errors</strong> at compilation time, not in runtime errors.</p></li>
  <li><p>Code that iterates over all properties, like <code>describe</code> function, should remain unchanged when I create a new property.</p></li>
  </ol>
  
  <p>Is it even possible to implement something like that with Typescript's type system?</p>