It is not possible to convert type parameters with arbitrary constraints. The spec mentions that (conversions):

[...] x can also be converted to type T if one of the following conditions applies:

  • Both V and T are type parameters and a value of each type in V's type set can be converted to each type in T's type set.
T1T2any
convertSliceT2(t1)convertSlice[string, chan func()]
CanConvertCanConvertfalse

If you choose to use generics, you are already making a choice towards type safety, so introducing reflection seems counter-intuitive. With generics, you do have to write functions for each set of convertible underlying types. The main special cases are:

Numbers:

type Number interface {
    constraints.Integer | constraints.Float
}

convertNumbers[T1, T2 Number](t1 []T1) []T2 {}

Strings — it is special-cased for byte slices and rune slices, but byte slices and rune slices aren't convertible to each other, so you'd need two functions here):

convertStrings[T1, T2 ~string | ~[]byte](t1 []T1) []T2 {}
// or
convertStrings[T1, T2 ~string | ~[]rune](t1 []T1) []T2 {}

Complex:

convertComplex[T1, T2 ~complex64 | ~complex128](t1 []T1) []T2 {}