Cannot use type assertion on type parameter

Issue

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;
}

Solution

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 type T … the notation x.(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.

Answered By – colm.anseo

Answer Checked By – Marilyn (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.