我具有以下接口和类型(所有接口和类型都可以更改)
interface Base {
type: string;
}
interface A extends Base {
type: "A";
field: string;
}
interface B extends Base {
type: "B";
query: string;
}
interface C extends Base {
type: "C";
equal: number;
}
type BaseExtensions = A | B | C;
interface BaseWrapper<R extends BaseExtensions> {
idType: string;
base: R;
}
interface And {
type: "AND";
rules: Array<BaseWrapper<any>>;
}
interface Or {
type: "OR";
rules: Array<BaseWrapper<any>>;
}
type Rule<R extends BaseExtensions> = BaseWrapper<R> | And | Or
Run Code Online (Sandbox Code Playgroud)
我想做的是编写以下函数:
function doAThingBasedOnTheRuleType(rule: Rule<any>): Thing {
if (isAnd(rule)) {
return DoAndThing(rule);
}
if (isOr(rule)) {
return DoOrThing(rule);
}
if (isA(rule.base)) {
return DoAThing(rule);
}
if (isB(rule.base)) {
return DoBThing(rule);
}
if (isC(rule.Base)) {
return DoCThing(rule);
}
// error, [ts] Function lacks ending return statement and return type does not include 'undefined'.
}
Run Code Online (Sandbox Code Playgroud)
我希望Rule会开始,因为And | Or | BaseWrapper<A> | BaseWrapper<B> | BaseWrapper<C>它应该一一缩小。但是,我得到了错误// error, [ts] Function lacks ending return statement and return type does not include 'undefined'.
1-为什么TS无法推断类型?2-如何解决?
我正在使用TS 2.5.2
TypeScript关于隐式返回的规则在语法上得到了执行-在不知道所涉及的类型的情况下,在函数的所有可到达出口点都需要有return语句。
要弄清楚使用类型系统无法实现给定函数的隐式返回,将需要多次“通过”,而类型系统当前不这样做(出于性能/复杂性的原因)。
例如,考虑以下代码:
function fn1() {
const f = fn2();
if (f === "alpha") {
return "A";
} else if (f === "beta") {
return "B";
}
}
function fn2() {
const f = fn1();
if (f === "A") {
return "alpha";
} else if (f === "B") {
return "beta";
}
return "gamma";
}
Run Code Online (Sandbox Code Playgroud)
什么是fn1()?这可能是"A" | "B" | undefined如果fn2()返回值比其他"alpha"或"beta",或者它可能是"A" | "B",如果这些是唯一返回值。好吧,让我们检查一下fn2()-它的返回类型是什么?这取决于fn1()- 的类型,如果仅fn2返回,"alpha" | "beta"则fn1返回"A" | "B";"alpha" | "beta" | "gamma"如果undefined可能的返回值,则返回。
因此,要弄清楚fn1隐式返回的可及性,您必须进行多次“回合”推理,在其中根据另一个函数的类型来优化一个函数的类型,然后重复进行,希望您达到了一个固定点并不会无限递归。这是一个很大的不仅仅是做与隐性收益的语法执行单次更昂贵。
最简单的解决方法是添加一个throw:
} else if (...) {
return ...;
}
throw new Error("Shouldn't be reachable");
}
Run Code Online (Sandbox Code Playgroud)
或者,如果您真的很喜欢代码覆盖,请if在最后一块中将条件重写为一个断言:
} else {
Debug.assert(x.kind === "B");
return "C";
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4264 次 |
| 最近记录: |