表題通りですが、一筋縄ではいかなかったので備忘録として残します。
ジェネリクスを使わない場合、下記は正しくキャストできます。
let hoge: Any? = nil
hoge as! String? // nil
しかし、ジェネリクス関数で同様のことを行う場合、 force unwrap によるエラーが発生してしまいます。
func convert<T>(_ value: Any?) -> T {
return value as! T
}
convert(nil) as String? // fatal error: unexpectedly found nil while unwrapping an Optional value
これは、もう一つジェネリクス関数を経由することで回避することができます。
func convert<T>(_ value: Any?) -> T {
func cast<U, V>(_ value: U, to type: V.Type) -> V {
return value as! V
}
return cast(value, to: T.self)
}
convert(nil) as String? // nil
※ 達成したかったことは Optional、非 Optional どちらも許容できるキャストの定義です。
struct Hoge {
let val1: String
let val2: String?
}
Hoge(val1: convert(dict["val1"]),
val2: convert(dict["val2"]))
// 逐一 `as` を書きたくない
Hoge(val1: dict["val1"] as! String,
val2: dict["val2"] as? String)