The Mysterious "some": Why Are Thousands of Developers Asking About It?
\n\nIf you've ever written in SwiftUI, you've definitely seen the some View construct. It looks simple, but beginners often get confused: "What is this 'some'? Why can't I just write View? And if I remove some — will it break?" The question "What is the 'some' keyword in Swift(UI)?" has gathered thousands of views on Stack Overflow — and for good reason. Behind this one short word lies a whole philosophy of modern Swift.
In this article, we'll figure out what the some keyword is, why it appeared in the language, and why SwiftUI is unimaginable without it. You'll learn how it relates to generics, protocols, and "opaque types." And most importantly — you'll understand how to write cleaner and more performant code.
\n\nThe Problem That "some" Solves
\n\nImagine you're writing a function that returns some object conforming to the View protocol. In SwiftUI, this happens all the time:
func makeGreeting() -> View {\n return Text("Hello!")\n}\n\nThe Swift compiler will say: "Protocol 'View' can only be used as a generic constraint because it has Self or associated type requirements." Sounds scary, but the point is simple: the View protocol in SwiftUI requires the type to be known at compile time. If we return View — that's an abstraction, but the compiler needs something concrete.
Previously, developers would work around this with generics:
\n\nfunc makeGreeting<T: View>() -> T {\n return Text("Hello!") as! T\n}\n\nThis worked, but it looked like a hack: you promise the compiler you'll return T, but you're actually "pretending." Plus, the calling code had to explicitly specify the type. Ugly and unsafe.
"some" — The Savior from Boilerplate Code
\n\nThe some keyword in Swift appeared in version 5.1 precisely for such cases. It tells the compiler: "I will return a concrete type that conforms to the protocol, but I don't want to name it. You determine it at compile time." This is called an opaque type.
Let's go back to our example:
\n\nfunc makeGreeting() -> some View {\n return Text("Hello!")\n}\n\nNow the code compiles! The compiler knows that exactly Text is returned, but from the outside we only see some View. This gives us two things:
- \n
- Type safety — the compiler checks that the return type is always the same. \n
- Encapsulation — we hide implementation details from the calling code. \n
Comparison: "some" vs Generics vs Protocols
\n\nTo better understand the magic of some, let's compare three approaches with a concrete example. Suppose we want to write a function that returns a shape (a circle or a square).
1. Returning a protocol (won't compile)
\n\nprotocol Shape {\n func draw()\n}\n\nstruct Circle: Shape {\n func draw() { print("Drawing a circle") }\n}\nstruct Square: Shape {\n func draw() { print("Drawing a square") }\n}\n\n// Error: Protocol 'Shape' cannot be used as a return type\nfunc makeShape() -> Shape {\n return Circle()\n}\n\nAs we already know — it doesn't work if the protocol has associated types or Self requirements.
\n\n2. Using generics
\n\nfunc makeShape<T: Shape>() -> T {\n // Need to somehow create T, but we don't know the concrete type\n fatalError("Cannot create generic")\n}\n\nProblem: the calling code must know what type to expect. The function cannot decide what to return on its own.
\n\n3. Using "some" (works perfectly)
\n\nfunc makeShape() -> some Shape {\n