H5W3
当前位置:H5W3 > 其他技术问题 > 正文

【前端问题精选】关于数组中 ts 函数类型的推导

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

// 例如一个数组
[() => 1, () => 's']
// 期望推导出
[number, string]

回答:

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>];
}

本文地址:H5W3 » 【前端问题精选】关于数组中 ts 函数类型的推导

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址