I am dealing with different units, i.e. distance, altitude, speed, volume, etc. 
My goal is to have an elegant, unique way to format them in the app, like for example calling myValue.formatted:
let mySpeed: Speed = 180
println(mySpeed.formatted) // 5.0 km/h
let myAltitude: Altitude = 4000
println(myAltitude.formatted) // 4000 m
I thought this was a good case for using type aliases.
typealias Distance = Float
typealias Altitude = Float
typealias Speed = Float
For the formatted property, I tried with an extension of the type Float:
extension Float {
    var formatted: String {
        get {
            switch self {
            case is Altitude:
                return "\(self) m"
            case is Speed:
                return "\(self * 3.6) km/h"
            default:
                return "\(self)"
            }
        }
    }
}
But the compiler says that my case blocks are always true.
Then i tried to extend the single type:
extension Speed {
  var formatted: String {
    return "\(self * 3.6) km/h"
  }
}
extension Altitude {
  var formatted: String {
    return "\(self) m"
  }
}
the compiler now clearly states Invalid redeclaration of 'formatted'
OK, it's clear now how type aliases work. But how would I get my .formatted property for different types of Floats in swift?
typealias just change or rename the type. It does not create another user type for you. You are actually extending Float for Speed, Altitude again.
You can pass 180 to your custom struct by conforming Literals types.
let mySpeed: Speed = 180
FloatLiteralConvertible and IntegerLiteralConvertible will give you same functionality you want and you can directly assign values to your custom struct types as you assign to Float
struct Speed: FloatLiteralConvertible,IntegerLiteralConvertible {
    var distance:Float
    init(floatLiteral value: Float) {
        distance = value
    }
    init(integerLiteral value: Int){
        distance = Float(value)
    }
    var formatted: String {
        return "\(distance * 3.6) km/h"
    }
}
let mySpeed: Speed = 180.0
println(mySpeed.formatted) // 5.0 km/h
                        Distance, Altitude, and Speed is always the same type - Float and share the same formatted property. This is how compiler sees your code:
extension Float {
    var formatted: String {
        get {
            switch self {
            case is Float:
                return "\(self) m"
            case is Float:
                return "\(self * 3.6) km/h"
            default:
                return "\(self)"
            }
        }
    }
}
I guess you need to create small wrappers for your functionality:
struct Distance {
    var value: Float
    var formatted: String {
        return "\(value) m"
    }
    init(_ value: Float) {
        self.value = value
    }
}
let myDistance = Distance(123)
myDistance.formatted
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With