Is there any way to make type interference work there? If I use and Array of Columns the type of Item is inferred but not when I use a ColumnBuilder.
struct ContentView: View {
@State var people = (1...100).map { Person(name: "Person \($0)", age: 20) }
var body: some View {
Table(items: people) { // Cannot convert value of type '() -> Array<Column<_>>' to expected argument type '() -> [Column<Person>]'
Column(title: "C1") {
Text("\($0.name)")
}
Column(title: "C2") {
Text("\($0.age)")
}
}
}
}
struct Table<Item: Identifiable> {
let columns: [Column<Item>]
let items: [Item]
init(items: [Item], @ColumnBuilder columns: () -> [Column<Item>]) {
self.items = items
self.columns = columns()
}
}
@_functionBuilder
struct ColumnBuilder {
static func buildBlock<Item>(_ columns: Column<Item>...) -> [Column<Item>] {
return columns
}
}
struct Column<Item> {
let title: String
let content: (Item) -> (AnyView)
init<Content: View>(title: String, content: @escaping (Item) -> Content) {
self.title = title
self.content = { AnyView(content($0)) }
}
}
xAlien95
(Stefano De Carolis)
2
You can make ColumnBuilder generic over the Item type and use buildExpression:
@resultBuilder
struct ColumnBuilder<Item> {
static func buildBlock(_ columns: Column<Item>...) -> [Column<Item>] {
return columns
}
static func buildExpression(_ column: Column<Item>) -> Column<Item> {
return column
}
}
struct Table<Item: Identifiable>: View {
let columns: [Column<Item>]
let items: [Item]
init(items: [Item], @ColumnBuilder<Item> columns: () -> [Column<Item>]) {
self.items = items
self.columns = columns()
}
var body: some View { ... }
}
As for why buildExpression helps the type checker, it is mentioned in SE-0289:
Side note: it would be nice to have a ready-to-be-executed code snippet. In this case the Person struct is missing and both Column and Table aren't conforming to View, so in order to check if there were other errors I needed to "fill the gaps" prior doing anything else 
1 Like
Thank you so much! I tried this approach but I missed buildExpression.
Sorry about that 