我试图做一个条件类型的函数,遇到这个stackoverflow问题,但不幸的是,它似乎不能很好地使用默认值(不管默认值在哪里),所以我遵循了那里的建议,使用过载代替。
事情似乎起作用了…直到我需要在包装器中调用该函数。下面是一个精简版:
// This works:
// Conditional type function with default value
// according to https://stackoverflow.com/questions/57057697
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);
}
打印稿操场
这段代码确实可以编译,但是你可以在操场上看到编译器抱怨check2()
中的check(t)
行不匹配任何过载,而在check3()
中它没有问题,即使我们在这两个函数中做完全相同的事情,只是冗余的类型检查。
这个行为是有意的吗?什么是正确的方式做条件类型函数与默认值?
有一个不同的重复问题,我相信它回答了你的问题。
下面是引用自该线程的公认答案的核心问题:
本质上,typescript不能像你期望的那样比较你的UnionType和每个重载。它在最后一个函数中起作用,因为您用冗余值检查保护了类型,从而告诉typescript,在进入check(t)之前,t只会是那些特定的值,因为存在重载。将联合传递给重载Typescript不能"拆分";的在根据重载签名检查它之前。它是检查Promise | string类型的变量单独过载。并集不能赋值给其成员,因此没有接受Promise的重载签名|字符串。
这是一个已知的行为和一些关于这个日期的GitHub问题年。
当你做check(t:UnionType)
没有那些多余的检查,它不会工作,因为它比较"one"|"two"|"three"
与"one"
,然后与"two"
,然后与"three"
。这些比较不相等,因此它失败了。