Look to the end to see my problem:
import Foundation
protocol NSNumberConvertible { }
extension NSNumberConvertible {
var asNSNumber: NSNumber {
// just force cast b/c we only conform this to known NSNumber convertible Numeric types
self as! NSNumber
}
}
extension Decimal: NSNumberConvertible { }
extension Double: NSNumberConvertible { }
extension Float: NSNumberConvertible { }
extension Int8: NSNumberConvertible { }
extension Int32: NSNumberConvertible { }
extension Int: NSNumberConvertible { }
extension Int64: NSNumberConvertible { }
extension UInt8: NSNumberConvertible { }
extension Int16: NSNumberConvertible { }
extension UInt: NSNumberConvertible { }
extension UInt64: NSNumberConvertible { }
extension UInt16: NSNumberConvertible { }
extension Bool: NSNumberConvertible { }
// Prefab one. Is there better way? Can't put this in SpellOutNumberFormatStyle with static computed property
// because with static computed property it's re-computed everytime
let ___$$$spellOutNumberFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .spellOut
return formatter
}()
struct SpellOutNumberFormatStyle<Value: NSNumberConvertible>: FormatStyle {
func format(_ value: Value) -> String {
___$$$spellOutNumberFormatter.string(from: value.asNSNumber)!
}
}
extension FormatStyle where Self == SpellOutNumberFormatStyle<Decimal> {
static var spellOut: Self { .init() }
}
extension FormatStyle where Self == SpellOutNumberFormatStyle<Double> {
static var spellOut: Self { .init() }
}
extension FormatStyle where Self == SpellOutNumberFormatStyle<Float> {
static var spellOut: Self { .init() }
}
extension FormatStyle where Self == SpellOutNumberFormatStyle<Int8> {
static var spellOut: Self { .init() }
}
extension FormatStyle where Self == SpellOutNumberFormatStyle<Int32> {
static var spellOut: Self { .init() }
}
extension FormatStyle where Self == SpellOutNumberFormatStyle<Int> {
static var spellOut: Self { .init() }
}
extension FormatStyle where Self == SpellOutNumberFormatStyle<Int64> {
static var spellOut: Self { .init() }
}
extension FormatStyle where Self == SpellOutNumberFormatStyle<UInt8> {
static var spellOut: Self { .init() }
}
extension FormatStyle where Self == SpellOutNumberFormatStyle<Int16> {
static var spellOut: Self { .init() }
}
extension FormatStyle where Self == SpellOutNumberFormatStyle<UInt> {
static var spellOut: Self { .init() }
}
extension FormatStyle where Self == SpellOutNumberFormatStyle<UInt64> {
static var spellOut: Self { .init() }
}
extension FormatStyle where Self == SpellOutNumberFormatStyle<UInt16> {
static var spellOut: Self { .init() }
}
extension FormatStyle where Self == SpellOutNumberFormatStyle<Bool> {
static var spellOut: Self { .init() }
}
let n = 3.1415926
print(n.formatted(.spellOut)) // three point one four one five nine two six
// ??? How to make it work for this generic:
func foo<T: BinaryFloatingPoint>(_ value: T) {
value.formatted(.spellOut) // error: error: ambiguous use of 'spellOut'
}
Edit: I solved it:
func foo<T: BinaryFloatingPoint>(_ value: T) -> String {
Double(value).formatted(.spellOut) // error: error: ambiguous use of 'spellOut'
}