【问题标题】:Union types: Typescript complains "Function lacks ending return statement and return type does not include 'undefined'.(2366)"联合类型:Typescript 抱怨“函数缺少结束返回语句并且返回类型不包括‘未定义’。(2366)”
【发布时间】:2020-07-05 03:13:27
【问题描述】:

这是我的代码。我有一个联合类型 CellType。我假设函数永远不会以 null、nothing、undefined 或 simular 调用。

我不想有任何 else 子句或最终的 return 语句,因为我知道所有情况都已处理。但不知何故,我错过了一些东西。我玩过旗帜。我收到警告

“函数缺少结束返回语句,返回类型不包括'undefined'.(2366)”为返回值CellType

class Empty {
};

class MyError  {
    type!: number;
}

type CellType = number | string | boolean | Empty | MyError;

function plusOne(v: CellType): CellType {
    if (typeof v === 'number') {
        return v+1;
    }
    if (typeof v === 'string') {
        return -1;
    }
    if (typeof v === 'boolean') {
        return -1;
    }        
    if (v instanceof Empty) { return 1; }
    if (v instanceof MyError) { return v; }
    // return { 'type':-1}
}

console.log(plusOne(10));
console.log(plusOne("hej"));

Playground Link

【问题讨论】:

    标签: typescript union-types


    【解决方案1】:

    你想要的是让 typescript 知道你已经涵盖了每一个案例;这被称为“穷举检查”,它是covered in the TypeScript docs

    文档建议您选择以下两种方法之一:

    首先是使用--strictNullChecks 进行编译,并确保您希望进行详尽检查的每个函数都使用显式返回类型进行注释。在实践中,这对于大多数代码库来说是不切实际的。

    第二个是在名为assertNever的库中添加一个小函数:

    function assertNever(x: never): never {
        throw new Error("Unexpected object: " + x);
    }
    

    然后在您的代码中,使用assertNever 表示应该涵盖所有可能的情况,如下所示:

    function plusOne(v: CellType): CellType {
        if (typeof v === 'number') {
            return v+1;
        }
        if (typeof v === 'string') {
            return -1;
        }
        if (typeof v === 'boolean') {
            return -1;
        }        
        if (v instanceof Empty) { return 1; }
        if (v instanceof MyError) { return v; }
        return assertNever(v);
    }
    

    如果您在到达assertNever 时还没有涵盖所有可能的情况,这将给您一个编译错误。

    【讨论】:

    • 更多信息:这个特殊问题是一个设计限制(请参阅microsoft/TypeScript#17358)。请注意,在 TS3.7 及更高版本中,您不必像 return assertNever(v) 中那样return 任何东西;你可以直接调用它...所以把它改成assertNever(v);
    • 添加 assertNever 解决了它。此外, Empty 应该定义为,因为没有任何字段的类使 plusOne({}) 正常,但它不应该这样做。类空{ __kind:“空”;构造函数() { this.__kind = "空" } }; var empty:Empty = new Empty()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-22
    • 2022-09-30
    • 2021-11-13
    • 1970-01-01
    • 2023-02-02
    • 1970-01-01
    相关资源
    最近更新 更多