We can't use type assertions on generic typed variables. This seems like really strange behavior considering it's allowed by interface{}
, but not by a generic constrained by interface{}
. Wondering if there are any work arounds?
// This works
func isInt(x interface{}) bool {
_, ok := x.(int)
return ok;
}
// Compile Error
// invalid operation: cannot use type assertion on type parameter
// value x (variable of type T constrained by interface{})
func isInt2[T interface{}](x T) bool {
_, ok := x.(int)
return ok;
}
CodePudding user response:
tl;dr
You can perform a type assertion only on interface values. So you must convert x
to a valid interface type first, any
/ interface{}
in this case:
func isInt[T any](x T) (ok bool) {
_, ok = any(x).(int) // convert, then assert
return
}
So why does this fail to compile?
_, ok = x.(int) // ... cannot use type assertion on type parameter value ...
More generally, x
's type T
is a type parameter, not an interface. It's only constrained by an interface. Moreover the Go (revised 1.18
) language spec explicitly states type parameters are not allowed in a type assertion:
For an expression
x
of interface type, but not a type parameter, and a typeT
... the notationx.(T)
is called a type assertion.
Also from from the generics tutorial on why parameter types need to be resolved at compile-time:
While a type parameter’s constraint typically represents a set of types, at compile time the type parameter stands for a single type – the type provided as a type argument by the calling code. If the type argument’s type isn’t allowed by the type parameter’s constraint, the code won’t compile.
CodePudding user response:
This works.
func isInt[T interface{}](x T) bool {
_, ok := interface{}(x).(int)
return ok
}
Example on Go Playground: https://go.dev/play/p/n_-Rdtx50ip