关于数组中 ts 函数类型的推导

可以推导出一个元组里所有函数的返回值类型吗?求解

// 例如一个数组
[() => 1, () => 's']
// 期望推导出
[number, string]
阅读 4.9k
2 个回答
const s = [() => 1, () => 's'] as const;
type S = typeof s;

type M<T extends ReadonlyArray<() => any>> = {
    -readonly [key in keyof T]: T[key] extends () => any ? ReturnType<T[key]> : never;
}
type R = M<S>;

这样试试

问题是这样推导出来有何作用?

因为 TypeScript 的类型及类型运算只能在编译器进行,换句话说,如果是运行时动态加载/生成的数据,是推导不出来类型的(或者只能推导出一般类型)。

既然如此,类型就只能在写代码的时候确定,那又何必这么麻烦的推导,直接写清楚不就好了吗?

type AFns = [() => number, () => string];
type AResults = [number, string]; 
const a : AFns = [() => 1, () => 's'];

// 可惜,不能从 .map 推导出元组类型,只能推导出数组类型
const r: AResults = a.map(fn => fn()) as AResults;
console.log(r);

补充

如果传入的参数类型相对固定,个数不定,用泛型数组

export function execAsync<T = unknown>(fns: (() => Promise<T>)[]): Promise<T>[] {
    return fns.map(fn => fn());
}

如果传入的参数个数确定,可以用元组。但是元组在处理过程中的类型是有可能没办法精确检查的(循环中多半会用数组类型来检查)。所以中间结果用 unknownany,最终结果强制声明过来,自己在内部逻辑中保证类型的正确性:

export function execAsync2(
    fns: [
        () => number,
        () => Promise<number>,
        () => Promise<string>,
    ]
): [Promise<number>, Promise<number>, Promise<string>] {
    const results = fns
        .map(fn => Promise.resolve(fn() as unknown));
    return results as [Promise<number>, Promise<number>, Promise<string>];
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进