打字稿在另一个函数中调用条件类型函数

Typescript calling conditional typed function within another function

我试图制作一个条件类型的函数,并遇到 , but unfortunately (默认值位于何处无关紧要),所以我听从了那里的建议并改用重载。

事情似乎确实有效...直到我需要在包装器中调用该函数。这是精简版:

// This works:
// Conditional type function with default value
// according to 
type UnionType="one"|"two"|"three";
// function check(t?:"one"):1; // Does not matter
function check(t:"one"):1;
function check(t:"two"):2;
function check(t:"three"):3;
function check(t:UnionType="one") {
  if(t=="one"){
    return 1;
  }else if(t=="two"){
    return 2;
  }else if(t=="three"){
    return 3;
  }
  return 1;
}

// This gives error:
// Calling that conditional type function within another function,
// using the same union type, but only one call
function check2(t:UnionType):1|2|3 {
  return check(t);// <--- complain
}

// This works though:
// Calling that conditional type fucntion within another function,
// using multiply identical call (redundant type check)
function check3(t:UnionType):1|2|3 {
  if(t=="one"){
    return check(t);
  }else if(t=="two"){
    return check(t);
  }else if(t=="three"){
    return check(t);
  }
  return check(t);
}

TypeScript playground

这段代码可以编译,但是你可以在操场上看到编译器抱怨 check2() 中的 check(t) 行不匹配任何重载,而 check3() 中没有问题,即使我们在这两个函数中做完全相同的事情,只是冗余类型检查。

这种行为是故意的吗?使用默认值执行条件类型函数的正确方法是什么?

我认为有一个不同的 可以解决您的问题。

这是从该线程上已接受的答案中引用的核心问题:

Passing Unions to An Overload Typescript is not able to "split up" the union before checking it against your overload signatures. It is checking your variable of type Promise | string against each overload individually. The union is not assignable to either of its members so there is no overload signature that accepts Promise | string.

This is a known behavior and some of the GitHub issues about this date back years.

本质上,打字稿无法像您期望的那样将您的 UnionType 与每个重载进行比较。它在最后一个函数中起作用,因为您已经通过冗余值检查来保护类型,从而告诉打字稿 t 将仅是进入检查(t)之前的那些特定值,其中存在重载。

当您在没有这些冗余检查的情况下执行 check(t:UnionType) 时,它将不起作用,因为它正在比较 "one"|"two"|"three""one",然后与 "two",然后与 "two" "three"。这些比较不等同,因此失败了。