Comparing enum cases while ignoring associated values

Multiple times I have now wanted to compare two values of an enum while ignoring their respective associated values.

enum Foo {
    case string(String)
    case number(Int)

let a = Foo.string("str")

a == Foo.string // Binary operator '==' cannot be applied to operands of type 'Foo' and '(String) -> Foo'

I understand why this doesn't work, but... I really want it to! Looking around the web for workarounds has led me to Erica Sadun's article, an interesting gist from the comments of said article, and even a post from Swift 1.2 era asking basically the same question.

All the solutions I've seen so far either require me to manually write type-specific code, or are plain ugly. Even if there are workarounds, though, I'd love for the following to work as well:


...which could only work if the cases without their associated values were somehow Equatable.

I suppose I'm posting this here out of frustration and hoping that perhaps someone from the Swift team will chime in, because this feels like it should work and just doesn't...


My only use of Sourcery is to auto-generate a subtype on my associated value enums so I can do simple == and != checks for their case names. I would love to see this feature exist in Swift.

It should be easy to do things like the following without resorting to weird quirks or a bunch of extra code

enum State {
  case ready
  case loading(reasons: [String])

let stateA = State.ready
let stateB = State.loading(reasons: ["ReasonA", "ReasonB"])

print( == //false

if != .loading { 
  // do something

There are a bunch of hiccups when writing if case let something = .enumCase (including the inability to use != with case let).
I too would love to see it simplified!

Relevant discussion regarding enum ergonomics: Automatically derive properties for enum cases

You can always do

if case .string = a { 
  print("found a string!") 

I think that, similar to SE-0194, the best way to provide this feature would be to add a CaseDiscriminatable (to be bike-shedded) protocol, for which, like CaseEnumerable a compiler-provided default implementation would be created for same-file extensions.


protocol CaseDiscriminatable {
  associatedtype Discriminator: Hashable
  var case: Discriminator

Here's a simple (if slightly verbose) way to do it:

enum Foo {
    case string(String)
    case number(Int)

   func hasSameCaseAs(_ type: Self) -> Bool {
      switch self {
         case .string: if case .string = type { return true }
         case .number: if case .number = type { return true }
      return false

var a = Foo.string("hello")
var b = Foo.number(6)
var c = Foo.number(5)

a.hasSameCaseAs(b) // returns false
b.hasSameCaseAs(c) // returns true
a.hasSameCaseAs(Foo.string("")) // returns true

Doesn't use the == operator but it's not really ==, is it?
As an aside, I'm unhappy with the form: if case .string = type { return true } too since its not an assignment but a comparison and would be better served by ==.

If the enum is Equatable, this first test works but the second doesn't, maybe it should?

a == .string("hello") // true
a == .string(_) // error: '_' can only appear in a pattern or on the left side of an assignment

To me if a == .string(_) looks so much better than if case .string(_) = a.

Hello. This topic is regularly being discussed. Some of the discussions:

As current workaround, you can use this solution:

But be careful and keep in mind, it is not safe and can be broken in future.

1 Like

this works now without brackets and Equatable requirement:

if case .string = a {

if to choose between:

if a == .string { // proposed
if .string == a { // same
if case .string = a { // existing

then +1 for the former form. interestingly Equatable requirement can be optional:

enum E {
    case string(String)
    case red
    case green
    case blue
if a == .string { // proposed: ok
if .string == a { // same
if a == .string("hello") { // error, 'Equatable' required
if a == .red { // error, 'Equatable' required
Terms of Service

Privacy Policy

Cookie Policy