Вместо того, чтобы пытаться иметь отдельные соответствия, вы можете создать отдельные реализации желаемой функции с различными ограничениями.
protocol ContainsString {
func contains<T>(_ substring: T) -> Bool where T: StringProtocol
}
extension Collection {
func filter<T>(by text: T) -> [Element] where T: StringProtocol, Element: ContainsString {
return filter { $0.contains(text) }
}
func filter<T>(by text: T) -> [Element] where T: StringProtocol, Element: Collection, Element.Element: ContainsString {
return filter { !$0.filter(by: text).isEmpty }
}
}
extension String: ContainsString {}
let strings = ["hello", "world"]
strings.filter(by: "hello") // ["hello"]
let stringOfStrings = [strings, ["foo", "bar"]]
stringOfStrings.filter(by: "hello") // ["hello", "world"]