Reputation: 23
I'm trying to add an extension to Observable. The code looks like this:
extension Observable where Element == ApiResponse<ItemsContainer<T>>, T:Codable
I'm receiving the following exception: Use of undeclared type T
.
So apparently this doesn't work.
The only thing missing is to constrain the generic inside ItemsContainer
to conform to Codable
.
Could be as simple as a syntactical issue or maybe I'm just not good enough with generics. Any help is appreciated!
Edit: To give the idea - ApiResponse and ItemsContainer look like this
public struct ApiResponse<ApiModel> {
public let data: ApiModel?
}
struct ItemsContainer<Items>: Codable where Items: Codable {
let items: [Items]
}
Upvotes: 1
Views: 1999
Reputation: 14780
You cannot constraint extensions to a Model Type which holds generic values, without specifying the Model Type of the generic value.
You only constrain protocols based on their associatedtype
s or generics based on their generic type, on the extension signature. Therefore T
is not recognized, because none of the protocols or generic declare it.
So by keeping in mind what I said above, a Model Type needs to be fully defined on the extension context. But wait that does not satisfy our requirement, we want it to be generic!
Then we do not need a Model Type, we need a protocol!
We have two Model Types (ApiResponse and ItemsContainer) which we need to know the generic type, therefore we need two protocols for each of them.
Let's create one named ApiResponseProtocol
public protocol ApiResponseProtocol {
associatedtype Model
var data: Model? { get }
}
Cool, the associatedtype Model
will play our role as the generic value for the ApiModel
on the object. Let's make ApiResponse
conform to ApiResponseProtocol
public struct ApiResponse<ApiModel>: ApiResponseProtocol {
public let data: ApiModel?
}
Generic ApiModel
here can be defined as Model
from the protocol.
Next steps would be the same for the ItemsContainer
public protocol ItemsContainerProtocol {
associatedtype Item
var items: [Item] { get }
}
public struct ItemsContainer<Items>: Codable, ItemsContainerProtocol where Items: Codable {
public let items: [Items]
}
Now since we can access each of the generic types from the protocol (associatedtypes
), the output would become something like this:
// This would be for example ApiResponse<ItemsContainer<Model>> where Model is a Model Type conforming to Codable
extension Observable where Element: ApiResponseProtocol, Element.Model: ItemsContainerProtocol, Element.Model.Item: Codable {}
Upvotes: 2