Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeScript: Exhaustiveness checing for enums breaks with EnumHandling.String #647

Closed
unekinn opened this issue Mar 7, 2018 · 3 comments
Closed

Comments

@unekinn
Copy link

unekinn commented Mar 7, 2018

In the template for generating enums, when DefaultEnumHandling = EnumHandling.String is set, the string value is cast to any.

This (among other things) removes a small nicety when working with TypeScript enums of literal types (string, number, boolean, null, undefined), namely exhaustiveness checking in switch statements.

There might well be a good reason to do the cast – please enlighten me if that's the case – but I present an example of my problem below.

Example

Consider the C# enum

public enum Status
{
    NotSet = 0,
    Approved = 1,
    Rejected = 2,
    Expired = 3
}

Which currently generates the following TypeScript enum (with EnumHandling.String)

export enum Status {
    NotSet = <any>"NotSet",
    Approved = <any>"Approved",
    Rejected = <any>"Rejected",
    Expired = <any>"Expired",
}

Now, imagine a function for getting an icon for a Status in TypeScript

type IconName = "question-mark" | "green-check" | "red-x" | "clock"

export function getStatusIcon(status: Status): IconName {
    switch (status) {
        case Status.NotSet:
            return "question-mark";
        case Status.Approved:
            return "green-check";
        case Status.Rejected:
            return "red-x";
        case Status.Expired:
            return "clock";
    }
}

The problem

getStatusIcon, as written above, does not compile. It gives the following error:

Function lacks ending return statement and return type does not include 'undefined'.

If we remove the <any> cast in the enum, getStatusIcon compiles.

The workaround is, of course, simple: adding a default case / ending return. But that means we lose the compile-time guarantee that if we add a new enum member, we must handle it in getStatusIcon.

@RicoSuter
Copy link
Owner

This any cast comes from the time when typescript didnt support string enums, see https://blog.rsuter.com/how-to-implement-an-enum-with-string-values-in-typescript/

Now that typescript directly supports string enums we can fix this. Do you know in which version typescript introduced string enums?

RicoSuter added a commit to RicoSuter/NSwag that referenced this issue Mar 7, 2018
@RicoSuter
Copy link
Owner

@unekinn
Copy link
Author

unekinn commented Mar 8, 2018

Great! 🎉
Thanks for the quick response, and for your work on this project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants