Swift
protocols
let
Swift programming
programming concepts

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:

swift
protocol UserIdentifiable {
    var id: String { get }
}

Or like this:

swift
protocol MutableUserIdentifiable {
    var id: String { get set }
}

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 }.

swift
1protocol Person {
2    var name: String { get }
3}
4
5struct User: Person {
6    let name: String
7}
8
9class Employee: Person {
10    var name: String
11
12    init(name: String) {
13        self.name = name
14    }
15}

Both types conform:

  • 'User uses let'
  • 'Employee uses var'

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:

swift
protocol Counter {
    var count: Int { get set }
}

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:

swift
protocol CounterView {
    var count: Int { get }
}

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 let because 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 let or var.
  • Use get set only when mutation through the protocol must be allowed.
  • Think of protocols as contracts for behavior, not blueprints for stored-property syntax.

Course illustration
Course illustration

All Rights Reserved.