Opaque Type (ondoorzichtig type) — is een Swift-mechanisme waarmee een functie een waarde van een bepaald type kan retourneren zonder het concrete type aan de aanroepende code bekend te maken. Het trefwoord some in het retourtype — het bekendste voorbeeld: some View in SwiftUI betekent "er wordt een type geretourneerd dat voldoet aan View, maar welk precies — implementatiedetail". Opaque type behoudt de identiteit van het type (in tegenstelling tot een protocol als type), waardoor de compiler code kan optimaliseren en consistentie van het retourtype garandeert. Volgens Swift Book, 2025 lossen opaque types het probleem van protocollen met associated types op, door waarden van dergelijke protocollen uit functies te kunnen retourneren.
Belangrijkste
Opaque Type — is een retourtype, gedeclareerd met het trefwoord some, dat de concrete implementatie verbergt voor de aanroepende code. De aanroepende partij weet alleen dat de geretourneerde waarde voldoet aan een bepaald protocol, maar weet niet welk concreet type achter some zit. Tegelijkertijd kent de compiler het exacte type en gebruikt het voor statische dispatch en optimalisatie.
Vóór de komst van opaque types in Swift 5.1 (SE-0244) was het onmogelijk om een protocol met associated types uit een functie te retourneren zonder boxing-wrapper. Het protocol Equatable heeft bijvoorbeeld een associated type en een functie kon niet eenvoudig Equatable retourneren — de compiler gaf de fout "protocol can only be used as a generic constraint". Opaque type loste dit probleem op.
func makeInt() -> some Equatable {
return 42
}
func makeString() -> some Equatable {
return "Hello"
}
// Compiler weet dat makeInt Int retourneert
// makeInt() == makeString() — ❌ fout, verschillende typen
Beide functies retourneren some Equatable, maar de concrete typen zijn verschillend: Int en String. Een poging om ze te vergelijken met == veroorzaakt een compilatiefout, omdat opaque type garandeert dat uit een concrete aanroep hetzelfde type wordt geretourneerd, maar niet tussen verschillende functies. Dit is een functie, geen bug: opaque type behoudt de type-identiteit waar een protocol als type (any Equatable) deze verliest.
Generic en Opaque Type — twee kanten van dezelfde medaille. Generic stelt de aanroepende code in staat het type te kiezen, terwijl opaque type de functie in staat stelt het type te verbergen voor de aanroepende code. Het verschil zit in de richting van de controle.
| Kenmerk | Generic | Opaque some |
|---|---|---|
| Wie kiest het type | Aanroepende code | Functie/methode |
| Type-identiteit | Behouden (stabiel) | Behouden (stabiel) |
| Aantal return-takken | Eén (via generic) | Hetzelfde type in alle takken |
| Toepassing | Algoritmen, gegevensstructuren | SwiftUI, fabrieksmethoden |
In een generic-functie beslist de caller welk type te gebruiken. De functie moet werken met elke T die aan de beperkingen voldoet. Voor opaque type kent de caller het concrete type niet — de implementatie neemt de beslissing.
// Generic: caller kiest type
func identity<T>(_ value: T) -> T { value }
let x: Int = identity(42)
// Opaque: functie verbergt type
func makeSomeEquatable() -> some Equatable { 42 }
let y = makeSomeEquatable()
De keuze tussen generic en opaque type hangt af van de intentie. Als de aanroepende code het type moet kiezen — gebruik generic. Als de functie implementatiedetails moet verbergen — gebruik some. SwiftUI koos voor some View juist omdat body van binnen flexibel maar van buiten stabiel moet zijn.
some — is een Swift-trefwoord, geïntroduceerd in Swift 5.1 (SE-0244). Het wordt gebruikt in retourpositie voor het declareren van opaque type, evenals in parameters (SE-0341) en eigenschappen. some garandeert dat het concrete type stabiel en bekend is bij de compiler, maar verborgen blijft voor externe code.
Vanaf Swift 5.7 kan some niet alleen in retourpositie worden gebruikt, maar ook in parameters. some Equatable in een parameter betekent "deze functie accepteert elk Equatable-type, maar alle aanroepen binnen de concrete body zien hetzelfde type".
func areEqual(_ a: some Equatable, _ b: some Equatable) -> Bool {
// a en b — potentieel verschillende typen, == werkt niet direct
return isEqual(a, b)
}
func isEqual<T: Equatable>(_ a: T, _ b: T) -> Bool {
return a == b
}
Het gebruik van some in parameters geeft een compactere syntax vergeleken met
any — is een Swift 5.6+ trefwoord voor het expliciet declareren van existentiële typen (protocol als type). In tegenstelling tot some wist any de type-identiteit: de compiler weet niet welk concreet type achter het protocol schuilgaat. Dit geeft flexibiliteit (verschillende typen kunnen in één array worden opgeslagen), maar ten koste van prestaties.
some — statisch polymorphisme: de compiler kent het concrete type, gebruikt directe dispatch en kan code inlinen. any — dynamisch polymorphisme: er wordt een virtuele methodentabel (existential container) gebruikt, wat indirectheid toevoegt.
protocol Drawable {
func draw()
}
// some: statisch type is bekend
func makeDrawable() -> some Drawable {
return Circle() // Enkel retourtype
}
// any: dynamisch, kan verschillende typen opslaan
var shapes: [any Drawable] = [Circle(), Square()]
shapes.append(Triangle())
De keuze tussen some en any is een compromis tussen prestaties en flexibiliteit. Some is sneller, maar beperkt tot één implementatie. Any is flexibeler (typen kunnen worden gemengd), maar langzamer vanwege dynamische dispatch. In SwiftUI wordt voor body altijd some View gebruikt, omdat de body van elke View één concreet type is.
Opaque Type lost een fundamenteel probleem van Swift op: protocollen met associated types (PAT) kunnen niet direct als type worden gebruikt. Een functie kan niet eenvoudig Collection retourneren — de compiler vereist dat Element wordt gespecificeerd. some Collection lost dit op door de associated type te verbergen.
Zonder opaque type zou voor het retourneren van Collection een concreet type (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 kan worden geïtereerd, maar de eigenschappen van ReversedCollection kunnen niet direct worden benaderd. Dit beschermt de inkapseling: als later reversed() wordt vervangen door een andere methode met een andere implementatie, zal de aanroepende code niet breken. Opaque type geeft de vrijheid om de implementatie te wijzigen zonder de API te veranderen.
some View — de bekendste toepassing van opaque type. Elke View in SwiftUI declareert body als some View. Dit betekent dat body een concreet View-type retourneert, maar de programmeur hoeft niet na te denken over wat precies — TupleView, Group, ModifiedContent of een ander type uit het framework.
Zonder opaque type zou body een concreet type moeten retourneren, bijvoorbeeld ModifiedContent<Button<Text>, Padding>, wat onpraktisch is. some View verbergt deze complexiteit. De compiler leidt het exacte type van body automatisch af tijdens compilatie.
struct ContentView: View {
var body: some View {
VStack {
Text("Hallo")
.font(.title)
Button("Raak me aan") {
print("Aangeraakt")
}
}
.padding()
}
}
De compiler leidt body af als ModifiedContent<VStack<TupleView<(Text, Button<Text>)>>, Padding>. De programmeur ziet some View. Als de layout van VStack naar HStack verandert, leidt de compiler automatisch het type opnieuw af — geen handmatige aanpassingen nodig. Dit is de magie van opaque type: de programmeur concentreert zich op de interfacelogica, niet op de compositietypen.
Veelgestelde vragen
Opaque Type — is een type gedeclareerd met het trefwoord some, dat de concrete implementatie verbergt voor de aanroepende code. De compiler kent het exacte type, maar de programmeur die de functie gebruikt ziet alleen het protocol.
some — is een opaque type met statische identiteit: de compiler kent het concrete type. any — is een existentieel type met dynamische dispatch: de type-identiteit is gewist. Some is efficiënter, any is flexibeler.
some View verbergt het complexe concrete type van body dat de compiler automatief afleidt. Dit bevrijdt de programmeur van de noodzaak om het exacte type bestaande uit Generic-wrappers (VStack, Group, ModifiedContent) te schrijven.
Ja, vanaf Swift 5.7. some in parameters is syntaxsugar over een generic-parameter. Het vereenvoudigt functiedeclaraties, vooral bij het werken met protocollen, waar elke some-parameter geen aparte
De compiler geeft een fout: opaque type vereist dat alle return-takken hetzelfde concrete type retourneren. Dit is bewust gedaan om de type-identiteit te behouden. Als u verschillende typen moet retourneren, gebruik dan any.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook