If it's just "one step" (the direct superclass of the type you're inspecting is Configurable<C> where C is a non-parametrized class), then it's
@SuppressWarnings("unchecked") <T> Class<? extends T> getConfigType(Class<? extends Configurable<? extends T>> clazz) {
String err = "configuration type of " + clazz + " is too hard to find";
if(!(clazz.getGenericSuperclass() instanceof ParameterizedType)) throw new UnsupportedOperationException(err);
var configurable = (ParameterizedType)clazz.getGenericSuperclass();
if(configurable.getRawType() != Configurable.class) throw new UnsupportedOperationException(err);
var args = configurable.getActualTypeArguments();
if(args.length != 1 || !(args[0] instanceof Class)) throw new UnsupportedOperationException(err);
return (Class<? extends T>)args[0];
}
You could modify this to search "harder": recursing up the superclasses until it finds Configurable, and maybe even tracking the assignments of type parameters so it can handle things like
class ConfigurableList<T> extends Configurable<List<T>> { }
class ConfigurableListBoolean extends ConfigurableList<Boolean> { }
but otherwise this seems to handle your case.
((ParameterizedType) ConfigurableBoolean.class.getGenericSuperclass()).getActualTypeArguments()[0]