Microsoft/TypeScript

Inferred type for accumulator and return value of `Array#reduce` is incorrect when used with `Record<string, unknown>`

Open

#59.196 aperta il 9 lug 2024

Vedi su GitHub
 (3 commenti) (0 reazioni) (0 assegnatari)TypeScript (6726 fork)batch import
Domain: check: Type InferenceHelp WantedPossible Improvement

Metriche repository

Star
 (48.455 star)
Metriche merge PR
 (Merge medio 6g 17h) (9 PR mergiate in 30 g)

Descrizione

🔎 Search Terms

"array reduce unknown"

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about Array#reduce

⏯ Playground Link

https://www.typescriptlang.org/play/?#code/PQKhCgAIUglBTAJgVwMYEsB2BzSBDTfAJyLwE9IB7AM0iPlUqMQGdIB3dAFwAtIWuRLLgBueADbJ4LKCGDhMeALbSADnlTxIAUQAey1ePgBBSAG8okK40wDipCgF5IAbQC6+NgkbMAPAKEcABp+QWEAPndLa0pbLjokNCRIZzwScgA6ehRNAApcjVQAShTw-FRUELMAX084BiZEfzDgyExkJQAjeCJwovBohJzk4GBIABUyVS10Nh96VHjc70bmwOwQ9q6evvBqgdAIaEgAZWUtPDY9AyNTeF1NVXjOXnxCNIcqWgXGthe+ZCYADWmEo7EIYkk0lk8kUKhY6k0On0SkM8AAQuZBjY7B9yClXB5LvUfE0AsIQoCQWDMJE3NjYnZsklEAS8WQsok8gUKiVHGVClVasSVn5ya0tt1ev1BszNKzRhMpjM2AA5ADy40g8wYSxYPEoyHErO6JNW4o2bQ6Ut2+3Ah1kp3OdWuqKMmPuj3ihQ6RrwXCYkFm2su8QDbyonQAVrrIFxlRxuHwCEHMIh7vx0NhFFxkPRUwJ4HhWTQEqSYQpzgiNFpXWiAMJYqwxOL2fHOdx1UVklqWqmg8F0hmtuXJVLpDmj-KFPkCipCupmVxA+BkABcoXWbg3kp6kGqMubQxZkEVk2mQbVmu1TAWeoNRpNWiXLhX683wm3Vu2RH3-TtDrHGcKguiiaIeg88BPImrwpuyXwRpQ0axvGF7-BGWDprombZv6eYzHERYlt8DTMBWcJqDWyI3PAAAiTbNji3oTgSnbEi+b4bhaX79jS+5REeTHHvKbITpywzTrypTlJU5jCl4pE9usmzWjsh7NqOCpjOeKqQBqWo6oskC5PqhrGpAprdmsFLfja-4HGAjrARcVxge6kCelB3oVL64j+oGwaoKGcaUPgtl7lghbFghPxkdAsJVoitZuRiDEtriLEdkSCmktZrS8YOAmMYy8SaaJDjiUkknFNJgpyXUu5EOpVhlWeCaBbesa5I19lAA

💻 Code

/**
 * Reducing an array of records with string values
 */
namespace ExampleA {
    const array = [] as Record<string, string>[]
    const reduced = array.reduce((acc) => acc, {} as Record<string, number>)

    reduced // Type is correct (Record<string, number>)
}

/**
 * Same as ExampleA except with an array of records with unknown values
 */
namespace ExampleB {
    const array = [] as Record<string, unknown>[]
    const reduced = array.reduce((acc) => acc, {} as Record<string, number>)

    reduced // Type is NOT correct (should be Record<string, number>)
}

/**
 * Same as ExampleB except accumulator is cast to an object type with an index signature instead of record
 */
namespace ExampleC {
    const array = [] as Record<string, unknown>[]
    const reduced = array.reduce((acc) => acc, {} as { [key: string]: number })

    reduced // Type is NOT correct (should be { [key: string]: number })
}

/**
 * Same as ExampleB except with an array of an object type with an index signature instead of record
 */
namespace ExampleD {
    const array = [] as { [key: string]: unknown }[]
    const reduced = array.reduce((acc) => acc, {} as Record<string, number>)

    reduced // Type is NOT correct (should be Record<string, number>)
}

/**
 * Same as ExampleB except accumulator is cast to a number instead of record
 */
namespace ExampleB {
    const array = [] as Record<string, unknown>[]
    const reduced = array.reduce((acc) => acc, {} as number)

    reduced // Type is correct (number)
}

🙁 Actual behavior

Inferred type of accumulator and return value of Array#reduce is Record<string, unknown> in the provided examples.

🙂 Expected behavior

Inferred type of accumulator and return value of Array#reduce should be based on the type of the initial value.

Additional information about the issue

No response

Guida contributor