【问题标题】:(TypeScript) argument gets its type from the union of its sibling's (all of which are fns) return types(TypeScript) 参数从其兄弟(所有这些都是 fns)返回类型的联合中获取其类型
【发布时间】:2019-11-04 16:39:23
【问题描述】:

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

这是我尝试过的:

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");

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

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

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

【问题讨论】:

    标签: typescript generics return union inference


    【解决方案1】:

    当编译器在那里看到一个异构数组字面量时,它会使用一些启发式方法来确定是为元素类型合成一个联合,还是在第一个与推断类型不匹配的元素上发出错误。这是一个权衡,因为有时您想要这样的错误。例如,以下错误通常被认为是可取的,如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&lt;F[number]&gt;

    我认为现在它应该可以正常工作了:

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

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

    Link to code

    【讨论】:

    • 这正是我所需要的。非常感谢@jcalz!
    猜你喜欢
    • 2020-07-30
    • 2021-06-02
    • 1970-01-01
    • 1970-01-01
    • 2021-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-27
    相关资源
    最近更新 更多