Opaque Type é um mecanismo do Swift que permite a uma função retornar um valor de algum tipo sem revelar o tipo concreto ao código chamador. A palavra-chave some no tipo de retorno é o exemplo mais famoso: some View em SwiftUI significa “a função retorna algum tipo que está em conformidade com View, mas qual exatamente é um detalhe de implementação.” Um opaque type preserva a identidade do tipo (diferentemente de um protocolo como tipo), o que permite ao compilador otimizar o código e garante a consistência do tipo retornado. De acordo com Swift Book, 2025, opaque types resolvem o problema de protocolos com tipos associados, permitindo retornar valores de tais protocolos de funções.
Principais pontos
Opaque Type é um tipo de retorno declarado com a palavra-chave some que oculta a implementação concreta do código chamador. Quem chama sabe apenas que o valor retornado está em conformidade com um determinado protocolo, mas não sabe exatamente qual tipo está por trás de some. Enquanto isso, o compilador conhece o tipo exato e o utiliza para despacho estático e otimização.
Antes da introdução dos opaque types no Swift 5.1 (SE-0244), era impossível retornar um protocolo com tipos associados de uma função sem um invólucro de boxing. Por exemplo, o protocolo Equatable tem um tipo associado, e uma função não podia simplesmente retornar Equatable — o compilador exibia um erro “o protocolo só pode ser usado como uma restrição genérica.” Opaque type resolveu este problema.
func makeInt() -> some Equatable {
return 42
}
func makeString() -> some Equatable {
return "Hello"
}
// O compilador sabe que makeInt retorna Int
// makeInt() == makeString() — ❌ erro, tipos diferentes
Ambas as funções retornam some Equatable, mas os tipos concretos são diferentes: Int e String. Tentar compará-los com == causará um erro de compilação porque um opaque type garante que uma chamada específica retorna o mesmo tipo, mas não entre funções diferentes. Isso é uma característica, não um erro: opaque type preserva a identidade do tipo onde um protocolo como tipo (any Equatable) a perde.
Generic e Opaque Type são dois lados da mesma moeda. Genéricos permitem ao código chamador escolher o tipo, enquanto opaque type permite à função ocultar o tipo do código chamador. A diferença está na direção do controle.
| Característica | Generic | Opaque some |
|---|---|---|
| Quem escolhe o tipo | Código chamador | Função/método |
| Identidade do tipo | Preservada (estável) | Preservada (estável) |
| Número de ramos de retorno | Um (via genérico) | Mesmo tipo em todos os ramos |
| Uso | Algoritmos, estruturas de dados | SwiftUI, métodos de fábrica |
Em uma função genérica, o caller decide qual tipo usar. A função deve funcionar com qualquer T que satisfaça as restrições. Para opaque type, o caller não conhece o tipo concreto — a implementação toma a decisão.
// Generic: o caller escolhe o tipo
func identity<T>(_ value: T) -> T { value }
let x: Int = identity(42)
// Opaque: a função oculta o tipo
func makeSomeEquatable() -> some Equatable { 42 }
let y = makeSomeEquatable()
A escolha entre generic e opaque type depende da intenção. Se o código chamador deve escolher o tipo, use genéricos. Se a função deve ocultar detalhes de implementação, use some. O SwiftUI escolheu some View precisamente porque body deve ser flexível internamente mas estável externamente.
some é uma palavra-chave do Swift introduzida no Swift 5.1 (SE-0244). É usada na posição de retorno para declarar um opaque type, bem como em parâmetros (SE-0341) e propriedades. some garante que o tipo concreto é estável e conhecido pelo compilador mas oculto do código externo.
A partir do Swift 5.7, some pode ser usado não apenas na posição de retorno mas também em parâmetros. some Equatable em um parâmetro significa “esta função aceita qualquer tipo Equatable, mas todas as chamadas dentro de um corpo específico veem o mesmo tipo.”
func areEqual(_ a: some Equatable, _ b: some Equatable) -> Bool {
// a e b — tipos potencialmente diferentes, == não funcionará diretamente
return isEqual(a, b)
}
func isEqual<T: Equatable>(_ a: T, _ b: T) -> Bool {
return a == b
}
Usar some em parâmetros fornece uma sintaxe mais concisa em comparação com
any é uma palavra-chave do Swift 5.6+ para declarar explicitamente tipos existenciais (protocolo como tipo). Ao contrário de some, any apaga a identidade do tipo: o compilador não sabe qual tipo concreto se esconde por trás do protocolo. Isso proporciona flexibilidade (você pode armazenar diferentes tipos em um único array), mas à custa do desempenho.
some — polimorfismo estático: o compilador conhece o tipo concreto, usa despacho direto e pode incluir código em linha. any — polimorfismo dinâmico: uma tabela de métodos virtuais (contêiner existencial) é usada, o que adiciona indireção.
protocol Drawable {
func draw()
}
// some: o tipo estático é conhecido
func makeDrawable() -> some Drawable {
return Circle() // Tipo de retorno único
}
// any: dinâmico, pode armazenar tipos diferentes
var shapes: [any Drawable] = [Circle(), Square()]
shapes.append(Triangle())
A escolha entre some e any é um compromisso entre desempenho e flexibilidade. Some é mais rápido mas se limita a uma única implementação. Any é mais flexível (você pode misturar tipos) mas mais lento devido ao despacho dinâmico. Em SwiftUI, body sempre usa some View porque o body de cada View é um tipo concreto.
Opaque Type resolve um problema fundamental do Swift: protocolos com tipos associados (PAT) não podem ser usados diretamente como tipo. Uma função não pode simplesmente retornar Collection — o compilador requer especificar Element. some Collection resolve isso ocultando o tipo associado.
Sem opaque type, retornar uma Collection exigiria usar um tipo concreto (Array
func makeReversedCollection<T>(
of array: [T]
) -> some Collection {
return array.reversed()
}
let result = makeReversedCollection(of: [1, 2, 3])
// result — ReversedCollection>, hidden from caller
for item in result {
print(item)
}
result pode ser iterado, mas você não pode acessar diretamente as propriedades de ReversedCollection. Isso protege o encapsulamento: se depois você substituir reversed() por outro método com uma implementação diferente, o código chamador não quebrará. Opaque type dá a liberdade de mudar a implementação sem mudar a API.
some View é o uso mais famoso de opaque type. Cada View em SwiftUI declara body como some View. Isso significa que body retorna algum tipo concreto de View, mas o desenvolvedor não precisa pensar exatamente o que é — TupleView, Group, ModifiedContent ou qualquer outro tipo do framework.
Sem opaque type, body teria que retornar um tipo concreto, por exemplo, ModifiedContent<Button<Text>, Padding>, o que é impraticável. some View oculta essa complexidade. O compilador infere o tipo exato de body automaticamente em tempo de compilação.
struct ContentView: View {
var body: some View {
VStack {
Text("Olá")
.font(.title)
Button("Toque-me") {
print("Tocado")
}
}
.padding()
}
}
O compilador infere body como ModifiedContent<VStack<TupleView<(Text, Button<Text>)>>, Padding>. O desenvolvedor vê some View. Se você mudar o layout de VStack para HStack, o compilador irá re-inferir automaticamente o tipo — sem edições manuais. Essa é a magia do opaque type: o desenvolvedor foca na lógica da interface, não nos tipos de composição.
Perguntas frequentes
Opaque Type é um tipo declarado com a palavra-chave some que oculta a implementação concreta do código chamador. O compilador conhece o tipo exato, mas o desenvolvedor que usa a função vê apenas o protocolo.
some é um opaque type com identidade estática: o compilador conhece o tipo concreto. any é um tipo existencial com despacho dinâmico: a identidade do tipo é apagada. Some é mais eficiente, any é mais flexível.
some View oculta o tipo concreto complexo de body, que o compilador infere automaticamente. Isso libera o desenvolvedor de ter que escrever o tipo exato composto por invólucros genéricos (VStack, Group, ModifiedContent).
Sim, a partir do Swift 5.7. Some em parâmetros é açúcar sintático sobre um parâmetro genérico. Simplifica declarações de função, especialmente ao trabalhar com protocolos onde cada parâmetro some não requer um
O compilador exibirá um erro: opaque type requer que todos os ramos de retorno retornem o mesmo tipo concreto. Isso é intencional para preservar a identidade do tipo. Se precisar retornar tipos diferentes, use any.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também