Generic parameter 'Element' could not be inferred
wousser opened this issue · 5 comments
Checklist
- Reviewed the README and documents.
- Searched existing issues for ensure not duplicated.
Expected Behavior
While updating from RC2 to RC4, the next issue happens.
Current Behavior
Array of class [ClassName], using the group function to list as cells.
cells: {
Group(of: state.todos.enumerated()) { offset, todo in
TodoText(todo: todo, isCompleted: false)
}}
Detailed Description (Include Screenshots)
However, using another class results in this error:
Generic parameter 'Element' could not be inferred. Explicitly specify the generic arguments to fix this issue
When explicitly specifying arguments I get the following error:
Unable to infer closure type in the current context.
What am I doing wrong?
Environment
- Carbon version:
RC4
The compiler may have output an incorrect error.
Is TodoText
conform to Identifiable Component
?
TodoText(todo: todo, isCompleted: false).identified(by: \.todo.id)
Isn't there any other parameters wrong?
BTW, thank you for opening some issues.
However, they were the general question related to the Swift type system, so please try-and-error by referring to the API doc before opening the issue.
Thanks for your quick answers.
The reason I'm asking here is that it worked with RC2, I didn't expect any breaking changes in an RC.
I'm trying to rewrite this part:
struct UpcomingEvent {
typealias ID = UUID
var id: ID
var date: Date
var events: [Any] // Contact, (Reminder, Contact), (Date, Contact)
}
struct State {
var upcomingEvents = [UpcomingEvent]()
}
Section(id: "upcoming") { section in
section.header = ViewNode(UpcomingHeader())
state.upcomingEvents.forEach({ event in
section.cells.append(
CellNode(UpcomingDateCard(date: event.date))
)
event.events.forEach({ (eventType) in
//contact
if let contact = eventType as? Contact {
section.cells.append(
CellNode(UpcomingContactCellNode(contact: contact))
)
}
//reminder
if let reminder = eventType as? (Reminder, Contact) {
section.cells.append(
CellNode(UpcomingReminderCellNode(reminder: reminder))
)
}
//birthday
if let birthday = eventType as? (Date, Contact) {
section.cells.append(
CellNode(UpcomingBirthday(birthday: birthday))
)
}
})
})
}
All CellNode's conform to Identifiable Component.
I tried to rewrite it as Group(of: ) but wasn't able to. Maybe you can share the best way to go ahead?
Dynamic type casting isn't compatible with function builder because if let
and switch
statements are not allowed.
I recommended to rewrite using enum, but you can also take the following workaround with legacy API.
This hasn't actually try to compiled, but it probably works.
Section(
id: "upcoming",
header: ViewNode(UpcomingHeader()),
cells: state.upcomingEvents.flatMap { event -> [CellNode] in
event.events.compactMap { eventType -> CellNode? in
//contact
if let contact = eventType as? Contact {
return CellNode(UpcomingContact(contact: contact))
}
//reminder
if let reminder = eventType as? (Reminder, Contact) {
return CellNode(UpcomingReminder(reminder: reminder))
}
//birthday
if let birthday = eventType as? (Date, Contact) {
return CellNode(UpcomingBirthday(birthday: birthday))
}
return nil
}
}
)
Another approach with function builder.
func component(for eventType: Any) -> AnyComponent? {
//contact
if let contact = eventType as? Contact {
return AnyComponent(UpcomingContactCellNode(contact: contact))
}
//reminder
if let reminder = eventType as? (Reminder, Contact) {
return AnyComponent(UpcomingReminderCellNode(reminder: reminder))
}
//birthday
if let birthday = eventType as? (Date, Contact) {
return AnyComponent(UpcomingBirthday(birthday: birthday))
}
return nil
}
Section(
id: "upcoming",
header:UpcomingHeader(),
cells: {
Group(of: state.upcomingEvents) { event in
Group(of: event.events.compactMap { eventType in
component(for: eventType)
}
}
}
)
Thanks for your help. That approach works great.