What is the “any” keyword in Swift?
Published on: March 15, 2022This article has been updated for Swift 5.7
With Swift 5.6, Apple added a new keyword to the Swift language: any
. If you see this in your code, you might think it’s similar to the some
keyword but it’s not quite the same thing.

In-app purchases made easy. RevenueCat provides everything you need to implement, manage, and analyze in-app purchases without managing servers or writing backend code.
Try RevenueCat now
This sponsored message helps keep the content on this site free. Please check out this sponsor as it directly supports me and this site.
Let’s take a look at the any
keyword as it’s intended to be used:
protocol Networking {
func fetchPosts() async throws -> [Post]
// ...
}
struct PostsDataSource {
let networking: any Networking
// ...
}
💡Tip: If you’re not familiar with Swift’s
some
keyword or need a refresher, check out this post on Swift’ssome
keyword.
While the any
keyword might look similar to the some
keyword in the sense that both are used in front of a protocol, and sound like they convey a message similar to “I don’t care what’s used for this type as long as it conforms to this protocol”, they’re really not the same at all.
While some
allows us to write code with generics that more or less ignores, or discards, a protocol’s associated types while expecting that every return value in a function that returns some Protocol
has the same concrete type, the any
keyword simply annotates that a given type is a so-called existential. For the sake of brevity, I won’t cover what an existential is in this post; that’s a topic for a different post. The bottom line is that an existential is like a "box type". You know something is, for example, a Pizza
(where Pizza
is defined as a protocol) but you have no idea what kind of pizza is in the box. You have to open the box to figure out which kind of pizza the box contains.
It's important to know that existentials are relatively expensive to use because the compiler and runtime can’t pre-determine how much memory should be allocated for the concrete object that will fill in the existential. Whenever you call a method on an existential, like the networking
property in the snippet you saw earlier, the runtime will have to dynamically dispatch this call to the concrete object which is slower than a static dispatch that goes directly to the concrete type.
The Swift team has determined that it’s currently too easy to reach for an existential over a concrete object. This essentially means that a lot of us are writing code that uses protocols (existentials) that harm our performance without us really being aware of it. For example, there’s nothing wrong with the following code, right?
protocol Networking {
func fetchPosts() async throws -> [Post]
// ...
}
struct PostsDataSource {
let networking: Networking
// ...
}
I’m sure we all have code like this, and in fact, we might even consider this best practice.
Sadly, this code uses an existential by having a property that has Networking
as its type. This means that it’s not clear for the runtime how much memory should be allocated for the object that will fill in our networking
property, and any calls to fetchPosts
will need to be dynamically dispatched.
By introducing the any
keyword, the language forces us to think about this. In Swift 5.6 annotating our let networking: Networking
with any
is optional; we can do this on our own terms. However, in Swift 6 it will be required to annotate existentials with the any
keyword.
As I was reading the proposal for any
, I realized that what the Swift team seems to want us to do, is to use generics and concrete types rather than existentials when possible. It’s especially this part from the introduction of the proposal that made this clear to me:
Despite these significant and often undesirable implications, existential types have a minimal spelling. Syntactically, the cost of using one is hidden, and the similar spelling to generic constraints has caused many programmers to confuse existential types with generics. In reality, the need for the dynamism they provided is relatively rare compared to the need for generics, but the language makes existential types too easy to reach for, especially by mistake. The cost of using existential types should not be hidden, and programmers should explicitly opt into these semantics.
So how should we be writing our PostsDataSource
without depending on a concrete implementation directly, and without using an existential since clearly existentials are less than ideal?
The easiest way would be to add a generic to our PostsDataSource
and constraining it to Networking
as follows:
protocol Networking {
func fetchPosts() async throws -> [Post]
// ...
}
struct PostsDataSource<Network: Networking> {
let networking: Network
// ...
}
By writing our code like this, the compiler will know up front which type will be used to fill in the Network
generic. This means that the runtime will know up-front how much memory needs to be allocated for this object, and calls to fetchPosts
can be dispatched statically rather than dynamically.
💡Tip: If you’re not too familiar with generics, take a look at this article to learn more about generics in Swift and how they’re used.
When writing PostsDataSource
as shown above, you don’t lose anything valuable. You can still inject different concrete implementations for testing, and you can still have different instances of PostsDataSource
with different networking objects even within your app. The difference compared to the previous approach is that the runtime can more efficiently execute your code when it know the concrete types you’re using (through generics).
The only thing we’ve lost is the ability to dynamically swap out the networking implementation by assigning a new value of a different concrete type to networking
(which we couldn’t do anyway because it’s defined as a let
).
So how useful is the any
keyword really? Should you be using it in Swift 5.6 already or is it better to just wait until the compiler starts enforcing any in Swift 6?
In my opinion, the any
keyword will provide developers with an interesting tool that forces them to think about how they write code, and more specifically, how we use types in our code. Given that existentials have a detrimental effect on our code’s performance I’m happy to see that we need to explicitly annotate existentials with a keyword in Swift 6 onward. Especially because it’s often possible to use a generic instead of an existential without losing any benefits of using protocols. For that reason alone it’s already worth training yourself to start using any
in Swift 5.6.
Note: take a look at my post comparing some and any to learn a bit more about how
some
can be used in place of a generic in certain situations.
Using any
now in Swift 5.6 will smoothen your inevitable transition to Swift 6 where the following code would actually be a compiler error:
protocol Networking {
func fetchPosts() async throws -> [Post]
// ...
}
struct PostsDataSource {
// This is an error in Swift 6 because Networking is an existential
let networking: Networking
// ...
}
The above code will need to be written using any Networking
in Swift if you really need the existential Networking
. In most cases however, this should prompt you to reconsider using the protocol in favor of a generic in order to improve runtime performance.
Whether or not the performance gains from using generics over existentials is significant enough to make a difference in the average app remains to be seen. Being conscious of the cost of existentials in Swift is good though, and it’s definitely making me reconsider some of the code I have written.
The any keyword in Swift 5.7
In Swift 5.7 the any
keyword is still not mandatory for all existentials but certain features aren't available to non-any
protocols. For example, in Swift 5.7 the requirements around protocols with a Self
requirement have been relaxed. Previously, if you wanted to use a protocol with an associated type of Self
requirement as a type you would have to use some
. This is why you have to write var body: some View
in SwiftUI.
In Swift 5.7 this restriction is relaxed, but you have to write any
to use an existential that has an associated type or Self
requirement. The following example is an example of this:
protocol Content: Identifiable {
var url: URL { get }
}
func useContent(_ content: any Content) {
// ...
}
The code above requires us to use any Content
because Content
extends the Identifiable
protocol which has an associated type (defined as associatedtype ID: Hashable
). For that reason, we have to use any
if we can't use some
.
The same is true for protocols that use a primary associated type. Using an existential with a primary associated type already requires the any
keyword in Swift 5.7.
Note that any
isn't a drop in replacement for some
as noted in my comparison of these two keywords. When using any
, you'll always opt-in to using an existential rather than a concrete type (which is what some
would provide).
Even though any
won't be completely mandatory until Swift 6.0 it's interesting to see that Swift 5.7 already requires any
for some of the new features that were made available with Swift 5.7. I think this reinforces the point that I made earlier in this post; try to start using any
today so you're not surprised by compiler errors once Swift 6.0 drops.