如何检查 TypeScript 中的 switch 块是否详尽? [英] How do I check that a switch block is exhaustive in TypeScript?

查看:39
本文介绍了如何检查 TypeScript 中的 switch 块是否详尽?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些代码:

enum Color {
    Red,
    Green,
    Blue
}

function getColorName(c: Color): string {
    switch(c) {
        case Color.Red:
            return 'red';
        case Color.Green:
            return 'green';
        // Forgot about Blue
    }

    throw new Error('Did not expect to be here');
}

我忘记处理 Color.Blue 案例,我更希望得到一个编译错误.如何构建我的代码,以便 TypeScript 将此标记为错误?

I forgot to handle the Color.Blue case and I'd prefer to have gotten a compile error. How can I structure my code such that TypeScript flags this as an error?

推荐答案

为此,我们将使用 never 类型(在 TypeScript 2.0 中引入),它表示不应该"的值发生.

To do this, we'll use the never type (introduced in TypeScript 2.0) which represents values which "shouldn't" occur.

第一步是写一个函数:

function assertUnreachable(x: never): never {
    throw new Error("Didn't expect to get here");
}

然后在 default 情况下(或等效地,在 switch 之外)使用它:

Then use it in the default case (or equivalently, outside the switch):

function getColorName(c: Color): string {
    switch(c) {
        case Color.Red:
            return 'red';
        case Color.Green:
            return 'green';
    }
    return assertUnreachable(c);
}

此时,您会看到一个错误:

At this point, you'll see an error:

return assertUnreachable(c);
       ~~~~~~~~~~~~~~~~~~~~~
       Type "Color.Blue" is not assignable to type "never"

错误消息表明您忘记包含在详尽开关中的情况!如果你忽略了多个值,你会看到一个关于例如的错误颜色.蓝色 |颜色.黄色.

The error message indicates the cases you forgot to include in your exhaustive switch! If you left off multiple values, you'd see an error about e.g. Color.Blue | Color.Yellow.

请注意,如果您使用 strictNullChecks,则需要在 assertUnreachable 调用之前使用 return(否则它是可选的).

Note that if you're using strictNullChecks, you'll need that return in front of the assertUnreachable call (otherwise it's optional).

如果你愿意,你可以变得更狂热.例如,如果您使用的是判别联合,则为了调试目的,在断言函数中恢复判别属性会很有用.它看起来像这样:

You can get a little fancier if you like. If you're using a discriminated union, for example, it can be useful to recover the discriminant property in the assertion function for debugging purposes. It looks like this:

// Discriminated union using string literals
interface Dog {
    species: "canine";
    woof: string;
}
interface Cat {
    species: "feline";
    meow: string;
}
interface Fish {
    species: "pisces";
    meow: string;
}
type Pet = Dog | Cat | Fish;

// Externally-visible signature
function throwBadPet(p: never): never;
// Implementation signature
function throwBadPet(p: Pet) {
    throw new Error('Unknown pet kind: ' + p.species);
}

function meetPet(p: Pet) {
    switch(p.species) {
        case "canine":
            console.log("Who's a good boy? " + p.woof);
            break;
        case "feline":
            console.log("Pretty kitty: " + p.meow);
            break;
        default:
            // Argument of type 'Fish' not assignable to 'never'
            throwBadPet(p);
    }
}

这是一个很好的模式,因为您可以获得编译时安全性,以确保您处理所有您期望的情况.如果你确实得到了一个真正超出范围的属性(例如,一些 JS 调用者组成了一个新的 species),你可以抛出一个有用的错误消息.

This is a nice pattern because you get compile-time safety for making sure you handled all the cases you expected to. And if you do get a truly out-of-scope property (e.g. some JS caller made up a new species), you can throw a useful error message.

这篇关于如何检查 TypeScript 中的 switch 块是否详尽?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆