Following code throws a compilation error
cannot use ExampleProps (variable of type Props[Example]) as Props[Generic] value in return statement
// Abstract
type Generic interface {
ID() string
}
type Props[G Generic] struct{}
// Example
type Example struct {
id string
}
func (example Example) ID() string {
return example.id
}
var ExampleProps = Props[Example]{}
// Problem
func Problem() Props[Generic] {
return ExampleProps
}
My question is: as Example
implements Generic
, why does Go not allow assigning Props[Example]
to Props[Generic]
?
Instantiating a generic type with different type arguments produces two new different named types.
Note that every time you supply a type argument, including in function arguments or return types, you are instantiating the generic type:
// Props is instantiated with type argument 'Generic'
func Problem() Props[Generic] {
return ExampleProps
}
Therefore Props[Example]
is just not the same type as Props[Generic]
and you can't use values of one type wherever the other one is expected. It does not matter if the types used as arguments themselves meet some condition for assignability, e.g. interfaces and implementors.
This is also true of generics instantiated with any
. The type any
is just another static type — alias of interface{}
. It's not equal to T
and it's not equal to "whatever type".
In simpler terms it’s as if you were using int
where string
is expected.
What you can do fix it and keep some flexibility is to instantiate Props
with a type parameter — whether this makes sense or not depends on how you actually plan to use this function. Anyway, as demonstration:
// adding a field to make this a bit less contrived
type Props[G Generic] struct{ Value G }
// Props instantiated with T, adequately constrained
func Problem[T Generic](v T) Props[T] {
return Props[T]{ Value: v }
}
func main() {
a := Problem(Example{})
fmt.Println(a)
}
Playground: https://gotipplay.golang.org/p/wcDOtJ6z80u