功能"缺少退货声明"但是有所有路径的挡板

时间:2017-09-26 18:54:30

标签: typescript

我有以下接口和类型(所有这些都可以更改)

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

我想做的是编写以下函数:

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'.

}

我希望规则从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上

2 个答案:

答案 0 :(得分:3)

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

fn1()的类型是什么?如果"A" | "B" | undefined返回fn2()"alpha"以外的值,则可以是"beta",如果这些是唯一的返回值,则可以是"A" | "B"。那么,让我们检查fn2() - 它的返回类型是什么?如果fn1()仅返回fn2,则 取决于"alpha" | "beta" - fn1返回"A" | "B"的类型,或返回{{1}如果"alpha" | "beta" | "gamma"是可能的返回值。

因此,要弄清楚undefined的隐式返回的可达性,你必须做多个“轮次”的推理,你可以根据另一个函数的类型细化一个函数的类型,然后重复,然后重复, 希望你达到一个固定点,不要无限递归。这比使用隐式返回的语法强制执行单次传递更加昂贵 lot

最简单的解决方法是简单地添加fn1

throw

或者,如果您真的进入代码覆盖范围,请将 } else if (...) { return ...; } throw new Error("Shouldn't be reachable"); } 条件重写为最后一个块中的断言:

if

答案 1 :(得分:1)

如果您不会抛出任何错误,并且isC是您的最后一个规则检查点,那么您是否无法删除该条件(因此始终会返回CThing)?

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

    return DoCThing(rule);
}