Opaque Type: cosa sono, some e any in Swift

Autore: IT Sectr Pubblicato: 2026-06-18 Tempo di lettura: 11 min

Opaque Type è un meccanismo di Swift che consente a una funzione di restituire un valore di qualche tipo senza rivelare il tipo concreto al codice chiamante. La parola chiave some nel tipo di ritorno è l’esempio più famoso: some View in SwiftUI significa “la funzione restituisce un tipo che è conforme a View, ma quale esattamente è un dettaglio implementativo.” Un opaque type preserva l’identità del tipo (a differenza di un protocollo come tipo), consentendo al compilatore di ottimizzare il codice e garantendo la coerenza del tipo restituito. Secondo Swift Book, 2025, gli opaque types risolvono il problema dei protocolli con tipi associati, consentendo di restituire valori di tali protocolli dalle funzioni.

Punti chiave

  • Opaque Type — un tipo di ritorno che nasconde l’implementazione concreta dal codice chiamante
  • some — la parola chiave per dichiarare un opaque type in posizione di ritorno
  • Identità del tipo preservata: il compilatore conosce il tipo concreto, a differenza di any
  • SwiftUI usa some View come metodo standard per dichiarare body
  • Limitazione: una funzione con some deve restituire lo stesso tipo concreto da tutti i rami

Cos’è un Opaque Type in Swift?

Opaque Type è un tipo di ritorno dichiarato con la parola chiave some che nasconde l’implementazione concreta dal codice chiamante. Il chiamante sa solo che il valore restituito è conforme a un determinato protocollo, ma non sa esattamente quale tipo si cela dietro some. Nel frattempo, il compilatore conosce il tipo esatto e lo utilizza per dispatch statico e ottimizzazione.

Il problema che Opaque Type risolve

Prima dell’introduzione degli opaque types in Swift 5.1 (SE-0244), era impossibile restituire un protocollo con tipi associati da una funzione senza un wrapper di boxing. Ad esempio, il protocollo Equatable ha un tipo associato, e una funzione non poteva semplicemente restituire Equatable — il compilatore dava un errore “il protocollo può essere usato solo come vincolo generico.” Opaque type ha risolto questo problema.

swift
func makeInt() -> some Equatable {
    return 42
}

func makeString() -> some Equatable {
    return "Hello"
}

// Il compilatore sa che makeInt restituisce Int
// makeInt() == makeString() — ❌ errore, tipi diversi

Entrambe le funzioni restituiscono some Equatable, ma i tipi concreti sono diversi: Int e String. Tentare di confrontarli con == causerà un errore di compilazione perché un opaque type garantisce che una specifica chiamata restituisca lo stesso tipo, ma non tra funzioni diverse. Questa è una caratteristica, non un bug: opaque type preserva l’identità del tipo là dove un protocollo come tipo (any Equatable) la perde.

Opaque Type vs Generic: qual è la differenza

Generic e Opaque Type sono due facce della stessa medaglia. I generics permettono al codice chiamante di scegliere il tipo, mentre opaque type permette alla funzione di nascondere il tipo dal codice chiamante. La differenza sta nella direzione del controllo.

CaratteristicaGeneric Opaque some
Chi sceglie il tipoCodice chiamanteFunzione/metodo
Identità del tipoPreservata (stabile)Preservata (stabile)
Numero di rami di ritornoUno (tramite generic)Stesso tipo in tutti i rami
UtilizzoAlgoritmi, strutture datiSwiftUI, metodi factory

Generic — scelta esterna

In una funzione generica, il chiamante decide quale tipo utilizzare. La funzione deve funzionare con qualsiasi T che soddisfi i vincoli. Per opaque type, il chiamante non conosce il tipo concreto — l’implementazione prende la decisione.

swift
// Generic: il chiamante sceglie il tipo
func identity<T>(_ value: T) -> T { value }
let x: Int = identity(42)

// Opaque: la funzione nasconde il tipo
func makeSomeEquatable() -> some Equatable { 42 }
let y = makeSomeEquatable()

La scelta tra generic e opaque type dipende dall’intenzione. Se il codice chiamante deve scegliere il tipo, usa i generics. Se la funzione deve nascondere i dettagli implementativi, usa some. SwiftUI ha scelto some View proprio perché body deve essere flessibile internamente ma stabile esternamente.

La parola chiave some e il suo uso

some è una parola chiave di Swift introdotta in Swift 5.1 (SE-0244). Viene utilizzata in posizione di ritorno per dichiarare un opaque type, oltre che in parametri (SE-0341) e proprietà. some garantisce che il tipo concreto sia stabile e noto al compilatore ma nascosto dal codice esterno.

some nei parametri di funzione

A partire da Swift 5.7, some può essere usato non solo in posizione di ritorno ma anche nei parametri. some Equatable in un parametro significa “questa funzione accetta qualsiasi tipo Equatable, ma tutte le chiamate all’interno di un corpo specifico vedono lo stesso tipo.”

swift
func areEqual(_ a: some Equatable, _ b: some Equatable) -> Bool {
    // a e b — tipi potenzialmente diversi, == non funzionerà direttamente
    return isEqual(a, b)
}

func isEqual<T: Equatable>(_ a: T, _ b: T) -> Bool {
    return a == b
}

Usare some nei parametri offre una sintassi più concisa rispetto a . È particolarmente utile nei protocolli e nel design orientato ai protocolli, dove ogni utilizzo di un protocollo non richiede un parametro generico separato. Il compilatore converte internamente i parametri some in generics, quindi le prestazioni sono identiche.

La parola chiave any e i tipi esistenziali

any è una parola chiave di Swift 5.6+ per dichiarare esplicitamente tipi esistenziali (protocollo come tipo). A differenza di some, any cancella l’identità del tipo: il compilatore non sa quale tipo concreto si nasconde dietro il protocollo. Questo offre flessibilità (puoi memorizzare tipi diversi in un singolo array), ma a scapito delle prestazioni.

some vs any: analisi comparativa

some — polimorfismo statico: il compilatore conosce il tipo concreto, utilizza dispatch diretto e può inlineare il codice. any — polimorfismo dinamico: viene utilizzata una tabella di metodi virtuali (contenitore esistenziale), che aggiunge indirezione.

swift
protocol Drawable {
    func draw()
}

// some: il tipo statico è noto
func makeDrawable() -> some Drawable {
    return Circle() // Tipo di ritorno singolo
}

// any: dinamico, può memorizzare tipi diversi
var shapes: [any Drawable] = [Circle(), Square()]
shapes.append(Triangle())

La scelta tra some e any è un compromesso tra prestazioni e flessibilità. Some è più veloce ma si limita a una singola implementazione. Any è più flessibile (puoi mescolare tipi) ma più lento a causa del dispatch dinamico. In SwiftUI, body usa sempre some View perché il body di ogni View è un tipo concreto.

Opaque Type nei protocolli con tipi associati

Opaque Type risolve un problema fondamentale di Swift: i protocolli con tipi associati (PAT) non possono essere utilizzati direttamente come tipo. Una funzione non può semplicemente restituire Collection — il compilatore richiede di specificare Element. some Collection risolve questo nascondendo il tipo associato.

Restituire PAT tramite some

Senza opaque type, restituire una Collection richiederebbe l’uso di un tipo concreto (Array) o l’eliminazione del tipo (AnyCollection). some Collection offre una via di mezzo: il compilatore conosce l’implementazione concreta, il codice chiamante no.

swift
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 può essere iterato, ma non puoi accedere direttamente alle proprietà di ReversedCollection. Questo protegge l’incapsulamento: se in seguito sostituisci reversed() con un altro metodo con un’implementazione diversa, il codice chiamante non si romperà. Opaque type ti dà la libertà di cambiare l’implementazione senza cambiare l’API.

Esempi pratici di some View in SwiftUI

some View è l’uso più famoso di opaque type. Ogni View in SwiftUI dichiara body come some View. Ciò significa che body restituisce qualche tipo concreto di View, ma lo sviluppatore non deve pensare a cosa sia esattamente — TupleView, Group, ModifiedContent o qualsiasi altro tipo del framework.

Come SwiftUI usa some View

Senza opaque type, body dovrebbe restituire un tipo concreto, ad esempio ModifiedContent<Button<Text>, Padding>, il che è poco pratico. some View nasconde questa complessità. Il compilatore deduce il tipo esatto di body automaticamente al momento della compilazione.

swift
struct ContentView: View {
    var body: some View {
        VStack {
            Text("Ciao")
                .font(.title)
            Button("Toccami") {
                print("Toccato")
            }
        }
        .padding()
    }
}

Il compilatore deduce body come ModifiedContent<VStack<TupleView<(Text, Button<Text>)>>, Padding>. Lo sviluppatore vede some View. Se cambi il layout da VStack a HStack, il compilatore dedurrà automaticamente il tipo — nessuna modifica manuale necessaria. Questa è la magia di opaque type: lo sviluppatore si concentra sulla logica dell’interfaccia, non sui tipi di composizione.

Domande frequenti

Cos’è un Opaque Type in Swift?

Opaque Type è un tipo dichiarato con la parola chiave some che nasconde l’implementazione concreta dal codice chiamante. Il compilatore conosce il tipo esatto, ma lo sviluppatore che usa la funzione vede solo il protocollo.

Qual è la differenza tra some e any in Swift?

some è un opaque type con identità statica: il compilatore conosce il tipo concreto. any è un tipo esistenziale con dispatch dinamico: l’identità del tipo viene cancellata. Some è più performante, any è più flessibile.

Perché SwiftUI usa some View?

some View nasconde il complesso tipo concreto di body, che il compilatore deduce automaticamente. Questo libera lo sviluppatore dalla necessità di scrivere il tipo esatto composto da wrapper generici (VStack, Group, ModifiedContent).

Si può usare some nei parametri di funzione?

, a partire da Swift 5.7. Some nei parametri è zucchero sintattico su un parametro generico. Semplifica le dichiarazioni di funzione, specialmente quando si lavora con protocolli dove ogni parametro some non richiede un separato.

Cosa succede se si restituiscono tipi diversi da una funzione some?

Il compilatore genererà un errore: opaque type richiede che tutti i rami di ritorno restituiscano lo stesso tipo concreto. È intenzionale per preservare l’identità del tipo. Se devi restituire tipi diversi, usa any.

Riepilogo

  • Opaque Type — nasconde il tipo concreto del valore restituito preservandone l’identità a livello di compilatore
  • La parola chiave some viene utilizzata per dichiarare un opaque type in posizione di ritorno e parametri
  • Generic vs Opaque: il chiamante sceglie il tipo per generic, l’implementazione sceglie per opaque
  • any — tipo esistenziale con dispatch dinamico, some — polimorfismo statico
  • SwiftUI some View — il caso d’uso principale: nasconde il tipo complesso di body dallo sviluppatore
  • Opaque type risolve il problema di restituire protocolli con tipi associati (PAT) dalle funzioni

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche