Opaque Type es un mecanismo de Swift que permite a una función devolver un valor de algún tipo sin revelar el tipo concreto al código llamante. La palabra clave some en el tipo de retorno es el ejemplo más conocido: some View en SwiftUI significa “la función devuelve algún tipo que cumple con View, pero cuál exactamente es un detalle de implementación.” Un opaque type preserva la identidad del tipo (a diferencia de un protocolo como tipo), lo que permite al compilador optimizar el código y garantiza la coherencia del tipo devuelto. Según Swift Book, 2025, los opaque types resuelven el problema de los protocolos con tipos asociados, permitiendo devolver valores de dichos protocolos desde funciones.
Puntos clave
Opaque Type es un tipo de retorno declarado con la palabra clave some que oculta la implementación concreta del código llamante. Quien llama solo sabe que el valor devuelto cumple con un determinado protocolo, pero no sabe exactamente qué tipo hay detrás de some. Mientras tanto, el compilador conoce el tipo exacto y lo utiliza para el despacho estático y la optimización.
Antes de la introducción de los opaque types en Swift 5.1 (SE-0244), era imposible devolver un protocolo con tipos asociados desde una función sin un envoltorio de boxing. Por ejemplo, el protocolo Equatable tiene un tipo asociado, y una función no podía simplemente devolver Equatable — el compilador mostraba un error “el protocolo solo se puede usar como una restricción genérica.” Opaque type resolvió este problema.
func makeInt() -> some Equatable {
return 42
}
func makeString() -> some Equatable {
return "Hello"
}
// El compilador sabe que makeInt devuelve Int
// makeInt() == makeString() — ❌ error, tipos diferentes
Ambas funciones devuelven some Equatable, pero los tipos concretos son diferentes: Int y String. Intentar compararlos con == provocará un error de compilación porque un opaque type garantiza que una llamada específica devuelve el mismo tipo, pero no entre diferentes funciones. Esto es una característica, no un error: opaque type preserva la identidad del tipo donde un protocolo como tipo (any Equatable) la pierde.
Generic y Opaque Type son dos caras de la misma moneda. Los genéricos permiten al código llamante elegir el tipo, mientras que opaque type permite a la función ocultar el tipo del código llamante. La diferencia está en la dirección del control.
| Característica | Generic | Opaque some |
|---|---|---|
| Quién elige el tipo | Código llamante | Función/método |
| Identidad del tipo | Preservada (estable) | Preservada (estable) |
| Número de ramas de retorno | Una (mediante genérico) | Mismo tipo en todas las ramas |
| Uso | Algoritmos, estructuras de datos | SwiftUI, métodos de fábrica |
En una función genérica, el caller decide qué tipo usar. La función debe funcionar con cualquier T que satisfaga las restricciones. Para opaque type, el caller no conoce el tipo concreto — la implementación toma la decisión.
// Generic: el caller elige el tipo
func identity<T>(_ value: T) -> T { value }
let x: Int = identity(42)
// Opaque: la función oculta el tipo
func makeSomeEquatable() -> some Equatable { 42 }
let y = makeSomeEquatable()
La elección entre generic y opaque type depende de la intención. Si el código llamante debe elegir el tipo, usa genéricos. Si la función debe ocultar detalles de implementación, usa some. SwiftUI eligió some View precisamente porque body debe ser flexible internamente pero estable externamente.
some es una palabra clave de Swift introducida en Swift 5.1 (SE-0244). Se usa en posición de retorno para declarar un opaque type, así como en parámetros (SE-0341) y propiedades. some garantiza que el tipo concreto es estable y conocido por el compilador pero oculto del código externo.
A partir de Swift 5.7, some se puede usar no solo en posición de retorno sino también en parámetros. some Equatable en un parámetro significa “esta función acepta cualquier tipo Equatable, pero todas las llamadas dentro de un cuerpo específico ven el mismo tipo.”
func areEqual(_ a: some Equatable, _ b: some Equatable) -> Bool {
// a y b — tipos potencialmente diferentes, == no funcionará directamente
return isEqual(a, b)
}
func isEqual<T: Equatable>(_ a: T, _ b: T) -> Bool {
return a == b
}
Usar some en parámetros proporciona una sintaxis más concisa en comparación con
any es una palabra clave de Swift 5.6+ para declarar explícitamente tipos existenciales (protocolo como tipo). A diferencia de some, any borra la identidad del tipo: el compilador no sabe qué tipo concreto se oculta detrás del protocolo. Esto proporciona flexibilidad (puedes almacenar diferentes tipos en un solo array), pero a costa del rendimiento.
some — polimorfismo estático: el compilador conoce el tipo concreto, usa despacho directo y puede incluir código en línea. any — polimorfismo dinámico: se usa una tabla de métodos virtuales (contenedor existencial), lo que añade indirección.
protocol Drawable {
func draw()
}
// some: el tipo estático es conocido
func makeDrawable() -> some Drawable {
return Circle() // Tipo de retorno único
}
// any: dinámico, puede almacenar diferentes tipos
var shapes: [any Drawable] = [Circle(), Square()]
shapes.append(Triangle())
La elección entre some y any es un compromiso entre rendimiento y flexibilidad. Some es más rápido pero se limita a una sola implementación. Any es más flexible (puedes mezclar tipos) pero más lento debido al despacho dinámico. En SwiftUI, body siempre usa some View porque el body de cada View es un tipo concreto.
Opaque Type resuelve un problema fundamental de Swift: los protocolos con tipos asociados (PAT) no se pueden usar directamente como tipo. Una función no puede simplemente devolver Collection — el compilador requiere especificar Element. some Collection resuelve esto ocultando el tipo asociado.
Sin opaque type, devolver una Collection requeriría usar un 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 se puede iterar, pero no se puede acceder directamente a las propiedades de ReversedCollection. Esto protege la encapsulación: si luego reemplazas reversed() por otro método con una implementación diferente, el código llamante no se romperá. Opaque type te da la libertad de cambiar la implementación sin cambiar la API.
some View es el uso más famoso de opaque type. Cada View en SwiftUI declara body como some View. Esto significa que body devuelve algún tipo concreto de View, pero el desarrollador no necesita pensar exactamente qué es — TupleView, Group, ModifiedContent o cualquier otro tipo del framework.
Sin opaque type, body tendría que devolver un tipo concreto, por ejemplo, ModifiedContent<Button<Text>, Padding>, lo cual no es práctico. some View oculta esta complejidad. El compilador infiere el tipo exacto de body automáticamente en tiempo de compilación.
struct ContentView: View {
var body: some View {
VStack {
Text("Hola")
.font(.title)
Button("Tócame") {
print("Tocado")
}
}
.padding()
}
}
El compilador infiere body como ModifiedContent<VStack<TupleView<(Text, Button<Text>)>>, Padding>. El desarrollador ve some View. Si cambias el diseño de VStack a HStack, el compilador reinferirá automáticamente el tipo — sin necesidad de ediciones manuales. Esta es la magia de opaque type: el desarrollador se enfoca en la lógica de la interfaz, no en los tipos de composición.
Preguntas frecuentes
Opaque Type es un tipo declarado con la palabra clave some que oculta la implementación concreta del código llamante. El compilador conoce el tipo exacto, pero el desarrollador que usa la función solo ve el protocolo.
some es un opaque type con identidad estática: el compilador conoce el tipo concreto. any es un tipo existencial con despacho dinámico: la identidad del tipo se borra. Some es más eficiente, any es más flexible.
some View oculta el complejo tipo concreto de body, que el compilador infiere automáticamente. Esto libera al desarrollador de tener que escribir el tipo exacto compuesto por envoltorios genéricos (VStack, Group, ModifiedContent).
Sí, a partir de Swift 5.7. Some en parámetros es azúcar sintáctico sobre un parámetro genérico. Simplifica la declaración de funciones, especialmente al trabajar con protocolos donde cada parámetro some no requiere un
El compilador mostrará un error: opaque type requiere que todas las ramas de retorno devuelvan el mismo tipo concreto. Esto es intencional para preservar la identidad del tipo. Si necesitas devolver diferentes tipos, usa any.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también