Skip to content

[Feature Request] The type checker should be able to infer string values of fields being switched on and match them to string literal types #49430

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

Closed
JonathanDCohen opened this issue Jun 8, 2022 · 5 comments
Labels
Duplicate An existing issue was already created

Comments

@JonathanDCohen
Copy link

JonathanDCohen commented Jun 8, 2022

Bug Report

πŸ”Ž Search Terms

switch
"string literal"

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about switch and "string literal"

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

interface I {
    field: string;
}

interface A extends I {
    field: "a";
}

function f(i: I) {
    switch(i.field) {
        case "a":
            /*
                Argument of type 'I' is not assignable to parameter of type 'A'.
                Types of property 'field' are incompatible.
                Type 'string' is not assignable to type '"a"'.
            */
            takesA(i);
    }
}

function takesA(a: A) {}

πŸ™ Actual behavior

Type checking fails to be able to infer the string value in the passed argument matches the string literal value in the type

πŸ™‚ Expected behavior

The type checker should know that inside the case statement, i.field === "a" and pass the type check

@MartinJohns
Copy link
Contributor

The types are not sealed. Just because there's "a" in that field, doesn't mean you're having a A. Your suggestion would be unsound and lead to bugs.

@jcalz
Copy link
Contributor

jcalz commented Jun 8, 2022

Duplicate of #16976, I think.

Narrowing the type of an object by checking a property only happens when the object is a discriminated union type and the property is its discriminant. But I is not a discriminated union (or any kind of union), so checking the field property only serves to narrow that property and not the whole object.

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Jun 8, 2022
@MartinJohns
Copy link
Contributor

@jcalz I don't see how 16976 is related.

@jcalz
Copy link
Contributor

jcalz commented Jun 9, 2022

In the example, the only difference between A and I is the type of the field property; once you narrow i.field to "a", then i is definitely an A. Indeed, you can write takesA({ ...i, field: i.field }) and the compiler is happy about it. It only has a problem with takesA(i) because narrowing i.field does not serve to narrow i, which is #16976.

@typescript-bot
Copy link
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

5 participants