-
-
Notifications
You must be signed in to change notification settings - Fork 491
Allow field access on concrete types behind interface values #951
Copy link
Copy link
Open
Description
Summary
- Allow property access on typed interface values by deferring field resolution to runtime, where the
concrete type can be inspected - At runtime, recursively traverse embedded interface fields to find properties on the underlying concrete
struct (e.g. Proxy → *Wrapper → Node(interface) → *Container → Items) - Method calls on interfaces without the method still produce compile-time errors
Motivation
When a method returns a typed interface (e.g. GetByID() Component), accessing fields on the concrete type behind that interface (result.Content) was rejected by the checker since the interface type has no such field.
This change defers property lookups on interface types to runtime, where reflection can inspect the actual value.
Real life issue
// Domain types (simplified)
type Component interface {
ID() string
}
type Header struct {
CompID string
}
func (h Header) ID() string { return h.CompID }
type WidgetCarouselV2 struct {
Header
Content []*Widget
}
type Widget struct {
Id string
}
type LoadingOrganism struct {
Component // embedded interface
}
type AsyncComponent struct {
*LoadingOrganism
}
type Components []Component
func (cs Components) GetByID(id string) Component {
for _, c := range cs {
if c.ID() == id {
return c
}
}
return nil
}
func main() {
c := &AsyncComponent{
LoadingOrganism: &LoadingOrganism{
Component: &WidgetCarouselV2{
Header: Header{CompID: "hero-carousel"},
Content: []*Widget{{Id: "promo-1"}},
},
},
}
// Before: fails with "cannot fetch Content from *domain.AsyncComponent"
// After: returns "promo-1"
output, err := expr.Eval(
`data.GetByID("hero-carousel")?.Content[0].Id`,
map[string]any{"data": Components{c}},
)
}Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels