(TypeScript)参数从其同级(所有均为fns)返回类型的并集中获取其类型

我正在尝试创建一个带有两个参数的通用函数,其中第一个是函数数组。第二个参数的类型应该是第一个参数的元素(所有都是函数)的返回类型的并集。

这是我尝试过的:

type Fn<R> = () => R;
const a: Fn<true> = () => true;
const b: Fn<"somen"> = () => "somen";

interface C<ABUnion,ABReturnUnion> {
  fns: ABUnion[];
  returns: ABReturnUnion;
}

function getX<R>(fns: Array<Fn<R>>,returns: R) {
  type FnsUnion = typeof fns[number];
  const c: C<FnsUnion,R> = {
    fns,returns,};
  return c;
}

getX([b,a],"true");

语言服务在b调用中为getX下划线,并显示以下错误:

  Type '"somen"' is not assignable to type 'true'.

有人知道解决方案吗?谢谢!

chenlin5818 回答:(TypeScript)参数从其同级(所有均为fns)返回类型的并集中获取其类型

当编译器看到异类数组文字时,它会使用一些启发式方法来确定是为元素类型综合一个联合,还是在第一个与推断类型不匹配的元素上产生错误。这是一个折衷,因为有时您会想要这样的错误。例如,如in a related question所述,以下错误通常被认为是可取的:

function same<T>(x: T,y: T) { };
same(0,""); // error!
// ---> ~~
// argument of type "" is not assignable to number

该函数可以变成如下数组示例:

function sameTuple<T>(x: [T,T]) { };
sameTuple([0,""]); // error!
// ---------> ~~
// Type 'string' is not assignable to type 'number'.

您会看到两难的情况……有时人们希望T成为联合,而有时人们希望将调用限制为同构数组。


在这种情况下,我建议将fns的类型更改为编译器愿意为其推断更宽泛的泛型的类型。例如:

function getX<F extends Array<() => any>>(fns: F,returns: ReturnType<F[number]>) {
  const c: C<F[number],ReturnType<F[number]>> = {
    fns,returns,};
  return c;
}

此处,通用类型F应该是与无参数函数数组匹配的任何内容。从fns的类型可以推断出这是最直接的事情。成功完成后,您可以将returns的类型合成为ReturnType<F[number]>

现在,它应该可以按照您的预期工作了,

getX([b,a],"somen"); // okay
getX([b,"true"); // error!
// --------> ~~~~~~
// "true" is not assignable to true | "somen".

好的,希望能有所帮助;祝你好运!

Link to code

本文链接:https://www.f2er.com/3165160.html

大家都在问