本文将深入探讨如何在 TypeScript 中编写类型定义,以便在函
数参数为一组函数时,能够准确推断返回数组的类型,同时保留每个元素的索引信息。我们将通过一个具体的代码示例,展示如何利用 readonly 和 ReturnType 等高级类型特性,实现精确的类型推断,避免类型信息丢失。
在 TypeScript 中,我们经常需要编写函数,接收一组函数作为参数,并返回一个由这些函数返回值组成的数组。一个常见的需求是,希望 TypeScript 能够准确推断返回数组的类型,并且保留每个元素的索引信息,例如,如果传入的函数分别返回 string 和 number,我们希望返回的类型是 [string, number],而不是 (string | number)[]。
TypeScript 默认会将可变参数推断为联合类型的数组,这会导致类型信息丢失。为了解决这个问题,我们需要更精确地定义函数类型。
以下代码展示了如何实现精确的类型推断:
const getValues:( ...args: T ) => { -readonly [P in keyof T]: ReturnType } = (...args) => args.map((arg) => arg()); const values = getValues( () => "a", () => 123 ); // values 的类型现在是: [string, number]
代码解释:
T extends readonly unknown[] | []: 这里使用了 readonly unknown[],确保传入的参数是一个只读数组。 | [] 允许不传参数。这保证了我们传入的参数是一个元组类型,而非一个简单的数组类型。
{ -readonly [P in keyof T]: ReturnType
(...args) => args.map((arg) => arg()): 这是函数的实际实现,它遍历传入的函数数组,并执行每个函数,然后将结果组成一个新的数组返回。
const getBooleans:( ...args: T ) => { -readonly [P in keyof T]: ReturnType } = (...args) => args.map((arg) => arg()); const booleans = getBooleans( () => true, () => false, () => true ); // booleans 的类型现在是: [boolean, boolean, boolean]
通过使用 readonly 和映射类型,我们可以编写出更精确的 TypeScript 类型定义,从而避免类型信息丢失,提高代码的可维护性和可读性。这种方法尤其适用于处理函数参数为一组函数,并需要精确推断返回数组类型的情况。