I have multiple string-derived enums that share a common Validate()
method (all outside of my control). I would like a generic method that converts a string to those enums and calls Validate()
on the resulting enum. I've tried to achieve this with generics but failed for various reasons.
In the example below the type constrained is too strong and prevents a call to Validate()
. I've also tried inserting my own interface with a Validate()
method and use it as a type constrained, but then failed on the type conversion part.
How can I achieve this without modifying the enums?
package main
// imagine i have multiple of those types outside of my control
type FooStatusEnum string
func NewFooStatusEnum(value FooStatusEnum) *FooStatusEnum {
return &value
}
const (
FooStatusEnumA FooStatusEnum = "A"
FooStatusEnumB FooStatusEnum = "B"
FooStatusEnumC FooStatusEnum = "C"
)
func (m FooStatusEnum) Validate() error {
return nil
}
func stringToValidatedEnum[E ~string](s string) E {
e := E(s)
if err := e.Validate(); err != nil {
panic(1)
}
return e
}
func main() {
stringToValidatedEnum[FooStatusEnum]("A")
e := FooStatusEnum("A")
e.Validate()
}
CodePudding user response:
Use a type constraint that both specifies string
underlying type and the Validate()
method:
type enumString interface {
~string
Validate() error
}
func stringToValidatedEnum[E enumString](s string) E {
e := E(s)
if err := e.Validate(); err != nil {
panic(1)
}
return e
}
Testing it:
result := stringToValidatedEnum[FooStatusEnum]("A")
fmt.Printf("%T %v", result, result)
This will output (try it on the Go Playground):
main.FooStatusEnum A