Why I can't use let in protocol in Swift?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
You cannot write let in a Swift protocol because a protocol describes required behavior, not stored-property implementation details. In Swift, let is a storage rule for a concrete type, while protocol property requirements are expressed only in terms of whether a property must be readable or writable.
What Protocols Are Allowed to Say
A protocol can require a property like this:
Or like this:
Those declarations say what operations must be supported:
- read-only
- read-write
They do not say whether the conforming type uses stored properties, computed properties, or some other implementation strategy.
Why let Does Not Fit the Model
let means "this specific stored property cannot change after initialization." That is an implementation choice of a concrete type.
A protocol cannot require that exact storage form because the conforming type might satisfy the requirement in several ways:
- a stored
let - a stored
var - a computed property with only a getter
Swift keeps protocols at the abstraction level of required access, not internal storage mechanics.
Read-Only Protocol Requirements Already Cover the Main Use Case
If what you want is "consumers may read this property but not set it through the protocol," use var name: Type { get }.
Both types conform:
- '
Useruseslet' - '
Employeeusesvar'
That flexibility is intentional.
Protocols Describe Capability, Not Storage
Think of protocol property requirements as API contracts:
- can callers read it
- can callers write it
That is what matters to the consumer of the protocol. Whether the underlying implementation stores the value, computes it, or forwards it somewhere else is not part of the contract.
This is the same reason protocol methods describe signatures and not the internal algorithm.
What Happens with get set
If the protocol says:
then a conforming type must provide both read and write access. A let property cannot satisfy that because it is immutable after initialization.
But if the protocol only says:
then either let or var can satisfy it, because both provide readable access.
Why This Design Is Useful
This rule keeps protocols flexible. If Swift allowed let inside protocols, the language would need to define how that interacts with:
- classes versus structs
- computed properties
- property wrappers
- protocol inheritance
Swift avoids that complexity by keeping the requirement focused on observable behavior instead.
Common Pitfalls
The biggest mistake is assuming var name: String { get } means the conforming type must use var. It does not. A let stored property can satisfy a get-only requirement perfectly well.
Another issue is trying to express immutability of storage in the protocol itself. Protocols are not the right tool for that level of constraint.
A third problem is forgetting that a read-only protocol requirement still allows the concrete type to be mutable internally. The restriction applies to the protocol view, not necessarily to the entire implementation.
Summary
- Swift protocols cannot use
letbecause protocols describe access requirements, not storage declarations. - Use
var property: Type { get }for read-only requirements. - A conforming type can satisfy a get-only requirement with either
letorvar. - Use
get setonly when mutation through the protocol must be allowed. - Think of protocols as contracts for behavior, not blueprints for stored-property syntax.

