Promisekit: Generic parameter 'T' could not be inferred

Created on 8 May 2018  路  7Comments  路  Source: mxcl/PromiseKit

Version 6 (Latest at time of writing)

I'm using this to allow for Codable support (plan to add a PR if I can get this working):

extension Alamofire.DataRequest {
    // Return a Promise for a Codable
    public func responseCodable<T: Codable>(decoder: JSONDecoder) -> Promise<T> {
        return Promise<T> { seal in
            responseData(queue: nil) { response in
                if let code = response.response?.statusCode {
                    //custom response code handling
                }
                switch response.result {
                case .success(let value):
                    do {
                        seal.fulfill(try decoder.decode(T.self, from: value))
                    } catch let e {
                        seal.reject(e)
                    }
                case .failure(let error):
                    seal.reject(error)
                }
            }
        }
    }
}

I'm converting all my Then to Done but I'm getting:

This says: Generic parameter 'T' could not be inferred on the Catch

func updateContactInformation(firstName: String, lastName: String, email: String, completion: @escaping (Bool, Error?) -> Void){
...
  Alamofire
    .request(urlPath, method: .get, encoding: URLEncoding.default, headers: headers)
    .responseCodable(decoder: self.defaultDecoder).done{ user in
        self.updateUserCache(user)
        completion(user, nil)
    }.catch{ error in
        print("ERROR updateContactInformation: \(error.localizedDescription)")
        completion(nil, error)
  } 
}

However, commenting out the self.updateUserCache and the print(), so that there's only one like, makes it successfully compile. How can I do both?

If I only remove the print() in the catch, I get this: 'Error' is not convertible to 'Error?'

Most helpful comment

How do I sepecify the type of user in done?

}.done { (user: User) in

All 7 comments

We already provide Codable support in our Alamofire extension.

Anyway, Swift is trying to figure out T, so to do this it uses your completion parameter, which takes (Bool, Error?), thus it is trying to use Decodable to produce Bool which is impossible.

Sorry, copy/paste error on my part. Also forgot to update pod for AlamofireKit, thanks for that.

I still can't figure it out. The only difference is the complete() function which splits it out. How can I force the T to MYUser codable?

//Working
func getUser(_ userId: String, completion: @escaping (MYUser?, Error?) -> Void) {
    func complete(_ user: MYUser){
        self.updateUserCache(user)
        completion(user, nil)
    }
    Alamofire
        .request(urlPath, method: .get, encoding: URLEncoding.default, headers: headers)
        .responseDecodable(decoder: self.defaultDecoder).done{ user in
            completion(user, nil)
        }.catch{ error in
            print("ERROR getUser: \(error.localizedDescription)")
            completion(nil, error)
    }
}

//Non-Working
func getUser(_ userId: String, completion: @escaping (MYUser?, Error?) -> Void) {
    Alamofire
        .request(urlPath, method: .get, encoding: URLEncoding.default, headers: headers)
        .responseDecodable(decoder: self.defaultDecoder).done{ user in
             self.updateUserCache(user)
             completion(user, nil)
        }.catch{ error in              <<< Generic parameter 'T' could not be inferred
            print("ERROR getUser: \(error.localizedDescription)")
            completion(nil, error)
    }
}

Also, removing the print():

}.catch{ error in
      completion(nil, error)             <<< 'Error' is not convertible to 'Error?'
}

It doesn't work because Swift can only infer types for one line closures.

You can make it work by specifying the type of user in you done.

This is mentioned in the troubleshooting guide.

@mxcl Thanks for the quick replies and your awesome work on this project (and homebrew)!

I'm not following the steps in your mention of Troubleshooting. How do I sepecify the type of user in done?

So I got the above example working by moving it to an internal function handler and reducing it to one line. Now I'm getting the same error for this one:

func loginFacebook(_ accessToken: String, completion: @escaping (Bool, Error?) -> Void){
        let urlPath = URL(string: self.endpoint + "rest-auth/facebook/")!
        let parameters ...
        func complete(){
            print("Updating user")
            ...
            completion(true, nil)
        }
        func completeError(_ error: Error){
            completion(false, error)
        }
        Alamofire
            .request(urlPath.absoluteURL, method: .post, parameters: parameters)
            .responseCodable(decoder: self.defaultDecoder)
            .then { me -> Promise<User> in
                print("Setting user copy locally, Signing into Firebase")
                self.currentUser = me
                return Auth.auth().signIn(withCustomToken: me.firebase_token!)
            }.done { _ -> () in
                complete()
            }.catch{ error in            <<<Generic parameter 'T' could not be inferred
                completeError(error)       
        }
    }

Before I added completeError() I was getting 'Error' is not convertible to 'Error?'. I can't follow either error and I've tried a lot of different permutations.

How do I sepecify the type of user in done?

}.done { (user: User) in

Thanks @nathanhosselton, @mxcl

Turns out I had to apply that to not-only the .done but the initial .then as well. Perhaps because I've got several subclasses of User.

The initial then was what required it, sorry, we missed the fact in your subsequent example it became a then. Key is that Swift needs to understand the type at that point.

Is this issue resolved? If so please close.

Was this page helpful?
0 / 5 - 0 ratings