C++ has this feature. When you define a template class, you can use SFINAE (or, in modern C++, concepts) to make it so that certain methods only exist if the template parameter meets certain requirements.
(Though even this is often unnecessary - for something like your `flatten` example, you could just go ahead and define it unrestricted. Methods of template classes are typechecked lazily - in other words, they don't need to successfully typecheck unless they're called. For this specific use case, SFINAE/concepts would just make the error message nicer.)
Rust also has this feature, with conditional impls.