Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you enforce a typealias in swift

Tags:

types

swift

I am trying to enforce a simple type backed by an Int does not get mixed up with other Ints.

Say you have the following typealiases :

typealias EnemyId = Int
typealias WeaponId = Int

I would like the following to have a compiler error:

var enemy: EnemyId = EnemyId("1")
enemy = WeaponId("1") // this should fail

The line I want to fail, should fail, because the two types (EnemyId and WeaponId) are different types.

What would be the nicest, cleanest way of achieving this?

UPDATE

After reviewing the answers and comments, I wanted to add what I came up with using enums:

enum Enemy {
    case id(Int)
    var id: Int {
        switch self {
        case .id(let i):
            return i
        }
    }
}
let enemy = Enemy.id(1)
print("enemy: \(enemy.id)")

Currently Mattt's answer is much shorter and more in line with what you expect in Swift.

UPDATE #2

I do not yet have access to swift 4.1 so I had to do the following:

  struct EnemyId : Hashable {
    private let value: Int

    init(_ value: Int) {
      self.value = value
    }

    init?(_ string:String) {
      guard let value = Int(string) else { return nil }
      self.init(value)
    }

    static func ==(_ lhs: EnemyId, _ rhs: EnemyId) -> Bool {
      return lhs.value == rhs.value
    }

    var hashValue: Int {
      return value.hashValue
    }
  }

It however turned out to add a couple of hundreds of milliseconds to my parsing, therefore I had to revert to the typealias, but it was very close to what I wanted.

like image 758
CodeReaper Avatar asked Dec 11 '22 08:12

CodeReaper


1 Answers

Note that in Swift 4.1 wrapper structs like Rob and Cristik are suggesting become trivial to write, because when you declare adoption of Hashable, you get automatically synthesized implementations of hashValue and == behind the scenes.

Thus, for your purposes, it might be sufficient to write:

struct EnemyId: Hashable {
    let value: Int
}
struct WeaponId: Hashable {
    let value: Int
}

You get the memberwise initializer init(value:) plus == plus hashValue "for free" in both cases.

like image 158
matt Avatar answered Jan 12 '23 18:01

matt