Reputation: 21
I would like to write a generic function which parses the result and return in success block of closure or sends back error in failure block.
I'm getting error like this 'Generic parameter 'T' could not be inferred'.
Here is my sample code.
let jsonString = """
{
"id": 1,
"msg": "Sample msg"
}
"""
struct Post: Codable {
var id: String?
var msg: String?
}
enum PostError: Error {
case empty
}
func fetch<T:Decodable>(_ completion: @escaping (Result<T?, PostError>) -> Void) {
do {
let data = Data(jsonString.utf8)
let post = try JSONDecoder().decode(T.self, from: data)
completion(.success(post))
}
catch {
completion(.failure(.empty))
}
}
fetch { res in
switch res {
case .success( let p):
print(p.description)
case .failure(let error):
print(error)
}
}
Here is the error I'm getting.
Upvotes: 1
Views: 268
Reputation: 2269
I understand what you're trying to do, but the main problem is that you never specify the type. The compiler knows you want to call fetch
but it doesn't know what you want to fetch or what to parse it to.
If you take a look at your fetch
call there is nowhere there where the compiler could possibly tell what you're trying to do or what you expect to happen.
You either have to:
func fetch<T: Decodable>(_ type: T.Type, _ completion: @escaping (Result<T, PostError>) -> Void) {
do {
let data = Data(jsonString.utf8)
let post = try JSONDecoder().decode(T.self, from: data)
completion(.success(post))
}
catch {
completion(.failure(.empty))
}
}
fetch(Post.self) { res in
switch res {
case .success(let p):
print(p)
case .failure(let error):
print(error)
}
}
or...
struct Fetcher<T: Decodable> {
func fetch(_ completion: @escaping (Result<T, PostError>) -> Void) {
do {
let data = Data(jsonString.utf8)
let post = try JSONDecoder().decode(T.self, from: data)
completion(.success(post))
}
catch {
completion(.failure(.empty))
}
}
}
let fetcher = Fetcher<Post>()
fetcher.fetch { res in
switch res {
case .success(let p):
print(p)
case .failure(let error):
print(error)
}
}
Upvotes: 0
Reputation: 163318
You can accept the generic type as a parameter, like so:
func fetchObject<T:Decodable>(ofType type: T.Type, _ completion: @escaping (Result<T, PostError>) -> Void) {
do {
let data = Data(jsonString.utf8)
let post = try JSONDecoder().decode(type, from: data)
completion(.success(post))
}
catch {
completion(.failure(.empty))
}
}
Usage:
fetchObject(ofType: Post.self) { res in
switch res {
case .success(let post):
print(post.description)
case .failure(let error):
print(error)
}
}
Upvotes: 1