Reputation: 433
I have following structs and functions.
struct ApiResponse<TResponse: Codable>: Codable {
var isSuccess: Bool
var mainResponse: TResponse?
}
public struct SomeResponse: Codable {
var someProperty: String
}
public func postAsync<TRequest: Codable, TResponse: Codable>(route: String, request: TRequest) async throws -> TResponse? {
let body = try JsonEncoder().encode(request)
let urlRequest = createUrlRequest(route: route, method: "POST", body: body)
let (data, _) = try await URLSession.shared.data(for: urlRequest)
let apiResponse = try JsonDecoder().decode(ApiResponse<TResponse>.self, from: data)
return response.mainResponse
}
I want to call postAsync
func like that but it says **Generic parameter 'TResponse' could not be inferred**
How can I call this method? I tried different ways but not solve.
- let res = await postAsync(route: "MyController/Get", request: someRequest) as? SomeResponse
- let res: SomeResponse = await postAsync(route: "MyController/Get", request: someRequest)
Upvotes: 2
Views: 726
Reputation: 299345
Your function doesn't return SomeResponse
, it returns SomeResponse?
, so what you meant here is:
let res = ... as SomeResponse? // Note `as`, not `as?`
or
let res: SomeResponse? = ...
I agree with EmilioPaleaz about how to improve the API, though I would recommend adding a default value, which gives the best of both worlds:
... request: TRequest, returning: TResponse.Type = TResponse.self) async throws -> ...
With this, when the return type is known, you can omit it.
Upvotes: 3
Reputation: 19882
I'm not sure why your attempted solutions failed, maybe they don't work with the async/await feature.
That said, while in general it's possible to use implicit generics, the more common practice in Swift is to include the type as one of the arguments, instead of keeping it implicit. That's the way it's done in classes like JSONDecoder
.
I would recommend changing your function signature to:
public func postAsync<TRequest: Codable, TResponse: Codable>(route: String, request: TRequest, receive: TResponse.Type) async throws -> TResponse? {
And calling it like this:
let res = await postAsync(route: "MyController/Get", request: someRequest, receive: SomeResponse.self)
Upvotes: 2