Can you force a Typealias in SWIFT?

I am trying to enforce a simple type supported by Int, which will not be confused with other Ints.

Assuming you have the following typealiases:

typealias EnemyId = Int
typealias WeaponId = Int

I want the following to have compilation errors:

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

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

What is the cleanest way to achieve this goal?

UPDATE

After reviewing the answers and comments, I want to use enumerations to add what I came up with:

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 The answer is much shorter and more in line with your expectations for Swift.

Update #2

I haven’t visited swift 4.1 yet so I have to do the following:

struct EnemyId: Hashable {
private let value: Int

init(_ value: Int) {
self.value = value< br /> }

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
}
}

However, it turns out that my parsing added a few hundred milliseconds, so I had to revert to the type, but it was very close to what I wanted.

< /div>

Swift does not (and there are? ) Has the concept of newtype-basically an opaque type that returns the same value as the original type.

What you can do is use a 1-field structure that wraps the original type. 1 field The structure has no performance loss, and at the same time provides you with a unique type with more semantic values ​​(thanks to @RobNapier for the excellent hints about Hashable):

struct EnemyId : Hashable {
private let value: Int

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

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

var hashValue: Int {
return value.hashValue
}
}

struct WeaponId: Hashable {
private let value: Int

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

static func ==(_ lhs: WeaponId, _ rhs: WeaponId) -> Bool {
return lhs.value == rhs.value
}< br />
var hashValue: Int {
return value.hashValue
}
}

Types like this can be used in many places like Int, And different. Of course, you can add more protocol conformance as needed.

I tried to enforce a simple type supported by Int, which will not be confused with other Ints.

Assuming you have the following typealiases:

t ypealias EnemyId = Int
typealias WeaponId = Int

I want the following to have compilation errors:

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.< /p>

What is the best and cleanest way to achieve this goal?

UPDATE

After reviewing the answers and comments, I want to use enumerations to add what I came up with:

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 The answer is much shorter and more in line with your expectations for Swift.

Update #2

I haven’t visited swift 4.1 yet so I have to do the following:

struct EnemyId: Hashable {
private let value: Int

init(_ value: Int) {
self.value = value< br /> }

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
}
}

However, it turns out that my parsing added a few hundred milliseconds, so I had to revert to the type, but it was very close to what I wanted.

Swift does not (and does?) have the concept of newtype-basically one An opaque type, it returns the same value as the original type.

What you can do is to use a 1-field structure that wraps the original type. The 1-field structure has no performance loss and provides you with A unique type with more semantic values ​​(thanks to @RobNapier for the excellent hint about Hashable):

struct EnemyId: Hashable {
private let value: Int

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

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

var hashValue: Int {
return value.hashValue
}
}

struct WeaponId: Hashable {
private let value: Int

init(_ value: Int) {self.value = value }
< br /> static func ==(_ lhs: WeaponId, _ rhs: WeaponId) -> Bool {
return lhs.value == rhs.value
}

var hashValue : Int {
return value.hashValue
}
}

Types like this can be used in many places like Int, but different. Of course, you can according to your needs Add more protocol conformance.

Leave a Comment

Your email address will not be published.