Swift为何无法正确推断该返回类型?
问题分析与解决
你的问题根源在于Swift编译器在Array的扩展上下文里,错误地将Array(firstCharacters)的初始化类型推断为Array<Cocktail>,而不是你期望的Array<String>,这才导致了那两个看似矛盾的错误。
为什么会出现这种情况?
因为你是在Array where Element == Cocktail的扩展里编写代码,编译器会优先把当前作用域内的Array类型(也就是Array<Cocktail>)作为初始化器的默认类型。当你调用Array(firstCharacters)时,编译器尝试把Set<String>转换成Array<Cocktail>——显然这做不到,于是就抛出了那两个错误:
- 第一个错误说“无法将Array
转成[any ScrollIndexable]”,其实是编译器错误推断出的初始化结果类型,不是你实际的 Set<String>对应的数组类型; - 第二个错误“调用初始化器无精确匹配”,是因为不存在从
Set<String>到Array<Cocktail>的初始化方法。
解决方法
只需要明确指定初始化的数组类型,或者直接将结果转换为[any ScrollIndexable],让编译器明确你的意图:
方案1:显式指定Array的元素类型
extension Array: ScrollIndexProviding where Element == Cocktail { var scrollIndices: [any ScrollIndexable] { let firstCharacters = reduce(into: Set<String>()) { partialResult, cocktail in guard let firstCharacter = cocktail.name.first else { return } partialResult.insert(String(firstCharacter)) } // 显式指定要创建String类型的数组 return Array<String>(firstCharacters) } }
方案2:直接转换为目标协议数组
也可以省略Array初始化,直接把Set转成[any ScrollIndexable]:
extension Array: ScrollIndexProviding where Element == Cocktail { var scrollIndices: [any ScrollIndexable] { let firstCharacters = reduce(into: Set<String>()) { partialResult, cocktail in guard let firstCharacter = cocktail.name.first else { return } partialResult.insert(String(firstCharacter)) } return Array(firstCharacters.map { $0 as any ScrollIndexable }) // 或者更简洁: // return firstCharacters.map { $0 } as [any ScrollIndexable] } }
这两种方式都能让编译器正确推断类型,解决编译错误。
内容的提问来源于stack exchange,提问作者Ziewvater
相关产品推荐
相关产品推荐

