title: How to properly index and modify generic partial
body: <p>This is my first generic type function and will appreciate if somebody could assist with my missing understanding of Partials and in general TS behaviour.</p>
  
  <p>What is intended to achieve:<br>
  1. Pass object of type <code>&lt;T&gt;</code><br>
  2. Modify it and return expected object of type <code>&lt;U&gt;</code></p>
  
  <p>The example below with the live warnings in codesandbox:
  <a href="https://codesandbox.io/s/small-wood-yq14e" rel="nofollow noreferrer">https://codesandbox.io/s/small-wood-yq14e</a></p>
  
  <p>P.S: I am open to new ideas of how the whole thing should be actually approached in TS best practices :-)</p>
  
  <pre><code>export type ObjectWithStrings = { [index: string]: string }
  
  
  // some demo data
  const CONTAINER_NUTRIENTS_NAMES_ORDER: ObjectWithStrings = {}
  const LIPIDS_NUTRIENTS_NAMES_ORDER: ObjectWithStrings = {}
  const NUTRIENTS_MODEL_MAP: ObjectWithStrings = {}
  
  function _sortNutrientsModel&lt;T&gt; (nutrientsModel: T) {
    const sortedNutrientsModel: Partial&lt;T&gt; = {}
  
    for (const sectionName in CONTAINER_NUTRIENTS_NAMES_ORDER) {
      if (CONTAINER_NUTRIENTS_NAMES_ORDER.hasOwnProperty(sectionName)) {
        /* 
        sortedNutrientsModel[sectionName]:
        Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Partial&lt;T&gt;'.
        No index signature with a parameter of type 'string' was found on type 'Partial&lt;T&gt;'.ts(7053)
  
        nutrientsModel[sectionName]:
        Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'unknown'.
        No index signature with a parameter of type 'string' was found on type 'unknown'.ts(7053) */
        sortedNutrientsModel[sectionName] = nutrientsModel[sectionName]
      }
    }
  
    for (const sectionName in LIPIDS_NUTRIENTS_NAMES_ORDER) {
      /* 
      Property 'lipids' does not exist on type 'T'.ts(2339) */
      if (LIPIDS_NUTRIENTS_NAMES_ORDER.hasOwnProperty(sectionName) &amp;&amp; sortedNutrientsModel.lipids.sections[sectionName]) {
        sortedNutrientsModel.lipids.sections[sectionName] = nutrientsModel.lipids.sections[sectionName]
      }
    }
  
    return sortedNutrientsModel
  }
  
  export function createNutrientsModel&lt;T extends object, U&gt; (nutrients: T) {
    const nutrientsModel: Partial&lt;U&gt; = {}
  
    for (const nutrientName in nutrients) {
      if (nutrients.hasOwnProperty(nutrientName)) {
        const nutrientLocation = NUTRIENTS_MODEL_MAP[nutrientName]
  
        if (typeof nutrientLocation === `string`) {
          const nutrientValues = nutrients[nutrientName]
  
          switch (nutrientLocation.length) {
            case 0: /* Container nutrient section */
              /*
              Type 'Extract&lt;keyof T, string&gt;' cannot be used to index type 'Partial&lt;U&gt;'.ts(2536) */
              if (typeof nutrientsModel[nutrientName] === `undefined`) {
               /*
                Type 'Extract&lt;keyof T, string&gt;' cannot be used to index type 'Partial&lt;U&gt;'.ts(2536) */
                nutrientsModel[nutrientName] = {}
              }
  
             /*
              Type 'Extract&lt;keyof T, string&gt;' cannot be used to index type 'Partial&lt;U&gt;'.ts(2536) */
              nutrientsModel[nutrientName].values = nutrientValues
              break
            default: /* Nutrient section */
             /*
              Type 'Extract&lt;keyof T, string&gt;' cannot be used to index type 'Partial&lt;U&gt;'.ts(2536) */
              if (nutrientsModel[nutrientLocation] === `undefined`) {
               /*
                Type 'Extract&lt;keyof T, string&gt;' cannot be used to index type 'Partial&lt;U&gt;'.ts(2536) */
                nutrientsModel[nutrientLocation] = {}
              }
  
             /*
              Type 'Extract&lt;keyof T, string&gt;' cannot be used to index type 'Partial&lt;U&gt;'.ts(2536) */   
              if (typeof nutrientsModel[nutrientLocation].sections === `undefined`) {
                nutrientsModel[nutrientLocation].sections = {}
              }
  
             /*
              Type 'Extract&lt;keyof T, string&gt;' cannot be used to index type 'Partial&lt;U&gt;'.ts(2536) */ 
              nutrientsModel[nutrientLocation].sections[nutrientName] = {
                values: nutrientValues
              }
          }
        }
      }
    }
  
    return _sortNutrientsModel(nutrientsModel) as U
  }
  </code></pre>
  
  <p>UPDATE with example of <strong>NutrientsType</strong></p>
  
  <pre><code>interface BalanceModelSection {
    DRI: {
      AI: number,
      AMDR: BalanceModelAMDR
      EAR: number,
      RDA: number,
      UL: number,
      unit: string
      [index: string]: string | number | BalanceModelAMDR
    }
  }
  
  interface BalanceRecordSectionValues {
    converted: {
      quantity: number
      recommended: number
      unit: string
    }
    quantity: number
    percentage: string
  }
  
  interface BalanceRecordSection extends
    BalanceRecordSectionValues,
    BalanceModelSection {}
  
  interface BalanceRecordNutrients {
    [index: string]: BalanceRecordSection | BalanceRecordProgressSection
    energy: BalanceRecordSection
  }
  </code></pre>