Microsoft/TypeScript

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

Open

#59,196 建立於 2024年7月9日

在 GitHub 查看
 (3 留言) (0 反應) (0 負責人)TypeScript (6,726 fork)batch import
Domain: check: Type InferenceHelp WantedPossible Improvement

倉庫指標

Star
 (48,455 star)
PR 合併指標
 (平均合併 6天 17小時) (30 天內合併 9 個 PR)

描述

🔎 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

貢獻者指南