2

I am getting the error "Operator '!==' cannot be applied to types" in the comparison with enums, but not with integer values:

enum E {
    A,
    B, 
    C,
    D,
    E,
    F
}

let x: E


// Operator '!==' cannot be applied to types 'E.A' and 'E.B'
if (x !== E.A || x !== E.B) {

}


// OK
if (x !== 0 || x !== 1) {

}

Aren't these two examples equivalent? What is the cause of the error?


Update

Actually it helps to consider the equivalent && expression:

if (!(x === E.A && x === E.B)) {

}

if (!(x === 0 || x === 1)) {

}

In the first example, compiler can infer that E.A and E.B are members of union types and cannot be equal, so gives the error, but it doesn't know (care) about integers.

4
  • What language version are you using? The error I get in the playground isn't "Operator '!==' cannot be applied to types", it's "Operator '!==' cannot be applied to types 'E.A' and 'E.B'". When the compiler statically knows that x is E.A, it'll disallow comparisons with any other type that isn't E.A. Commented Oct 31, 2017 at 22:33
  • Actually, the updated condition !(x === E.A && x === E.B) still makes no sense. x cannot be identical to E.A and E.B at the same time. Commented Nov 1, 2017 at 7:35
  • Yes, maybe I was not clear enough, but I can reason about the updated condition better than the negated one that it doesn't make sense. But !(x === 1 && x === 1) also doesn't make sense, I wonder why TypeScript doesn't complain about it. Commented Nov 1, 2017 at 9:09
  • There may be an error in the "Update" section: (x !== 0 || x !== 1) should become !(x === 0 && x === 1), and not !(x === 0 || x === 1) as appears above (commenting rather than editing as I'm not 100% certain I didn't miss something...) Commented Feb 19, 2019 at 11:00

1 Answer 1

4

You can find an identical example in the TypeScript documentation about enums:

enum E {
    Foo,
    Bar,
}

function f(x: E) {
    if (x !== E.Foo || x !== E.Bar) {
        //             ~~~~~~~~~~~
        // Error! Operator '!==' cannot be applied to types 'E.Foo' and 'E.Bar'.
    }
}

In that example, we first checked whether x was not E.Foo. If that check succeeds, then our || will short-circuit, and the body of the ‘if’ will get run. However, if the check didn’t succeed, then x can only be E.Foo, so it doesn’t make sense to see whether it’s equal to E.Bar.

The condition in your example thus makes no sense to the compiler. It will always evaluate to true anyway.

Because of that, TypeScript can catch silly bugs where we might be comparing values incorrectly.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the link to the documentation. I updated the question with the insight that I got from reading the documentation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.