When assigning values in Swift, Xcode may report an error such as:
Cannot assign value of type 'String' to type 'Int'
Another common form is:
Cannot assign value of type 'Int' to type 'String'
This error means that the type of the value being assigned does not match the type accepted by the destination variable, property, collection, or other storage location.
Common causes include mixing String with Int or Double, assigning optional values to non-optional storage, using incompatible array or dictionary element types, confusing enums with raw values, mismatching generic types, and mixing SwiftUI bindings with ordinary values.
The quickest way to diagnose the issue is to compare the two types shown in the compiler error and determine which type your program should actually use.
- What does “Cannot assign value of type” mean?
- How is this different from “Cannot convert value of type”?
- Typical situations where the error appears
- Common causes
- 1. Assigning String to Int
- 2. Assigning Int to String
- 3. Assigning Double to Int
- 4. Assigning an optional to a non-optional
- 5. Assigning Int(String) directly to Int storage
- 6. Array element types differ
- 7. Dictionary value types differ
- 8. A dictionary subscript receives the wrong value type
- 9. A String is assigned directly to an enum
- 10. Generic collection types differ
- 11. Result has the wrong success type
- 12. Tuple element types differ
- 13. A SwiftUI Binding is treated as a plain value
- 14. A plain value is used where a Binding is required
- 15. map returns the wrong collection element type
- 16. compactMap produces a different type than expected
- 17. API response properties have different types
- 18. Numeric types such as CGFloat and Double differ
- 19. A closure has an incompatible function type
- 20. Protocol or generic constraints do not allow the assignment
- What to check first
- Solution 1: Convert String to Int
- Solution 2: Validate String-to-Int conversion with guard
- Solution 3: Convert Int to String
- Solution 4: Convert Double to Int carefully
- Solution 5: Convert Int to Double
- Solution 6: Unwrap an optional before assignment
- Solution 7: Use a meaningful default value
- Solution 8: Make the destination optional when nil is valid
- Solution 9: Match array element types
- Solution 10: Convert a String array into an Int array
- Solution 11: Convert an Int array into a String array
- Solution 12: Match dictionary value types
- Solution 13: Convert an enum raw value into the enum
- Solution 14: Convert an enum to its raw value
- Solution 15: Match every tuple element type
- Solution 16: Match Result success types
- Solution 17: Distinguish SwiftUI bindings from values
- Solution 18: Pass the correct binding to child views
- Solution 19: Use the wrapped value where a Binding is not required
- Solution 20: Convert numeric types explicitly
- Solution 21: Map transport models into domain models
- Solution 22: Match generic parameters
- Solution 23: Match closure function types
- Solution 24: Make map result types explicit
- Solution 25: Distinguish optional arrays from arrays
- Solution 26: Handle optional dictionaries explicitly
- Solution 27: Unwrap the result of as?
- Solution 28: Avoid forced casts as a shortcut
- Solution 29: Prefer structured models over Any
- Solution 30: Break complex expressions into intermediate variables
- If you need to assign String to Int
- If you need to assign String? to String
- If you need to assign Int? to Int
- If the error involves arrays
- If the error involves dictionaries
- If the error occurs in SwiftUI
- If the error occurs in Picker
- If the error occurs after a network request
- If the values appear compatible but Swift still rejects the assignment
- What you should avoid
- Fast troubleshooting checklist
- Summary
What does “Cannot assign value of type” mean?
Once a Swift variable or property has a concrete type, you can normally assign only compatible values to it.
This is valid:
var count: Int = 10
count = 20
This is not:
var count: Int = 10
count = "20"
The assigned value is a String while count stores Int values.
How is this different from “Cannot convert value of type”?
You may also see:
Cannot convert value of type 'String' to expected argument type 'Int'
That wording often appears at function and initializer call sites.
“Cannot assign value of type” is commonly associated with assignment to a variable, property, collection element, or other typed storage.
Both diagnostics usually represent the same fundamental issue: the source and destination types do not match.
Typical situations where the error appears
- Assigning String to an Int property
- Assigning Int to a String property
- Assigning Double to Int
- Assigning an optional to non-optional storage
- Mixing optional and non-optional collection values
- Assigning arrays with different element types
- Assigning dictionary values with the wrong type
- Assigning a raw value directly to an enum
- Using incompatible generic arguments
- Using the wrong tuple element types
- Confusing SwiftUI Binding values with ordinary values
- Mapping API response types directly into incompatible domain-model fields
- Mixing CGFloat, Double, Int, and other numeric types
- Assigning map or compactMap results to the wrong collection type
Common causes
1. Assigning String to Int
var age: Int = 0
age = "20"
2. Assigning Int to String
var text: String = ""
text = 100
3. Assigning Double to Int
var count: Int = 0
count = 10.5
Int and Double are different Swift types.
4. Assigning an optional to a non-optional
let name: String? = "Alice"
var displayName: String = ""
displayName = name
String? and String are different types.
5. Assigning Int(String) directly to Int storage
let text = "100"
var number: Int = 0
number = Int(text)
Int(text) returns Int?, because conversion can fail.
6. Array element types differ
var numbers: [Int] = [1, 2, 3]
numbers = ["1", "2", "3"]
7. Dictionary value types differ
var scores: [String: Int] = [:]
scores = [
"Alice": "100"
]
8. A dictionary subscript receives the wrong value type
var scores: [String: Int] = [:]
scores["Alice"] = "100"
9. A String is assigned directly to an enum
enum Status: String { case active case inactive }
var status: Status = .active
status = "inactive"
10. Generic collection types differ
var values: Array<String> = []
values = [1, 2, 3]
11. Result has the wrong success type
var result: Result<String, Error>
result = .success(100)
12. Tuple element types differ
var user: (String, Int)
user = ("Alice", "20")
13. A SwiftUI Binding is treated as a plain value
With:
@State private var name = ""
name is String, while $name is Binding<String>.
14. A plain value is used where a Binding is required
The inverse mismatch occurs when a SwiftUI API expects Binding<String> but receives String.
15. map returns the wrong collection element type
let numbers = [1, 2, 3]
var texts: [String] = []
texts = numbers.map { value in
value
}
The map expression returns [Int], not [String].
16. compactMap produces a different type than expected
The collection element type is determined by the closure’s returned value.
17. API response properties have different types
For example, a transport model may represent age as String while your domain model expects Int.
18. Numeric types such as CGFloat and Double differ
UI and graphics code may require explicit conversion between concrete numeric types.
19. A closure has an incompatible function type
When assigning a closure to a property, its parameter and return types must match the property’s function type.
20. Protocol or generic constraints do not allow the assignment
In generic and protocol-heavy code, inspect the full constrained type rather than only the apparent value shape.
What to check first
1. Compare the two types in the diagnostic
For:
Cannot assign value of type 'String' to type 'Int'
you have:
- Assigned value: String
- Destination: Int
2. Inspect the declaration of the destination
If it is:
var age: Int
ask whether age should genuinely be represented as an Int throughout the application.
Important: Do not convert values merely to silence the compiler. First determine which type correctly represents the data.
Solution 1: Convert String to Int
var age: Int = 0
let text = "20"
if let value = Int(text) {
age = value
}
Int(String) returns Int?, so conversion failure must be handled.
Solution 2: Validate String-to-Int conversion with guard
func updateAge(from text: String) { guard let value = Int(text) else { print("Invalid age") return }
age = value
}
Solution 3: Convert Int to String
var text = "" let count = 100
text = String(count)
String interpolation is another option:
text = "\(count)"
Solution 4: Convert Double to Int carefully
let price = 10.8
let integerPrice = Int(price)
Warning: Converting a floating-point value directly to Int discards its fractional part. Apply the rounding behavior your application actually requires.
For example:
let integerPrice = Int(price.rounded())
Solution 5: Convert Int to Double
let count = 10
let value: Double = Double(count)
Solution 6: Unwrap an optional before assignment
let name: String? = "Alice"
var displayName: String = ""
if let name {
displayName = name
}
Solution 7: Use a meaningful default value
displayName = name ?? "Unknown"
Solution 8: Make the destination optional when nil is valid
var displayName: String?
displayName = name
Only make storage optional when absence is genuinely part of the data model.
Solution 9: Match array element types
var numbers: [Int] = [1, 2, 3]
numbers = [4, 5, 6]
Solution 10: Convert a String array into an Int array
let strings = ["1", "2", "3"]
let numbers: [Int] = strings.compactMap { value in
Int(value)
}
Note: compactMap removes elements that fail conversion. If every element is required, validate failures explicitly rather than silently dropping values.
Solution 11: Convert an Int array into a String array
let numbers = [1, 2, 3]
let strings: [String] = numbers.map { value in
String(value)
}
Solution 12: Match dictionary value types
var scores: [String: Int] = [:]
scores["Alice"] = 100
If the application intentionally stores textual scores:
var scores: [String: String] = [:]
scores["Alice"] = "100"
Solution 13: Convert an enum raw value into the enum
enum Status: String { case active case inactive }
let text = "active"
if let value = Status(rawValue: text) {
status = value
}
Solution 14: Convert an enum to its raw value
let status: Status = .active
let text: String = status.rawValue
Solution 15: Match every tuple element type
Incorrect:
var user: (String, Int)
user = ("Alice", "20")
Correct:
user = ("Alice", 20)
Solution 16: Match Result success types
var result: Result<String, Error>
result = .success("Completed")
If the success value should be Int:
var result: Result<Int, Error>
result = .success(100)
Solution 17: Distinguish SwiftUI bindings from values
@State private var name = ""
name is String.
$name is Binding<String>.
TextField requires the binding:
TextField("Name", text: $name)
Solution 18: Pass the correct binding to child views
struct EditView: View { @Binding var name: String
var body: some View {
TextField("Name", text: $name)
}
}
struct ContentView: View {
@State private var name = ""
var body: some View {
EditView(name: $name)
}
}
Solution 19: Use the wrapped value where a Binding is not required
Text(name)
Do not pass $name to an API that expects a plain String.
Solution 20: Convert numeric types explicitly
let count: Int = 100
let width: CGFloat = CGFloat(count)
let value: Double = Double(count)
Solution 21: Map transport models into domain models
struct UserResponse: Decodable { let age: String }
struct User {
let age: Int
}
func makeUser(
from response: UserResponse
) -> User? {
guard let age = Int(response.age) else {
return nil
}
return User(age: age)
}
Converting at the boundary keeps the rest of the application consistently typed.
Solution 22: Match generic parameters
struct Box<Value> { var value: Value }
var box = Box(value: 10)
box is Box<Int>, so this is invalid:
box.value = "Hello"
If the box should store strings:
var box = Box(value: "Hello")
Solution 23: Match closure function types
If a property is declared as:
var handler: (Int) -> String
the assigned closure must accept Int and return String:
handler = { value in String(value) }
Solution 24: Make map result types explicit
let numbers = [1, 2, 3]
let texts: [String] = numbers.map { value in
String(value)
}
Solution 25: Distinguish optional arrays from arrays
This is invalid:
let loadedUsers: [User]? = loadUsers()
var users: [User] = []
users = loadedUsers
If an empty array is an appropriate default:
users = loadedUsers ?? []
Be careful when nil and “zero results” represent different states.
Solution 26: Handle optional dictionaries explicitly
let response: [String: Int]? = loadScores()
var scores: [String: Int] = [:]
scores = response ?? [:]
Solution 27: Unwrap the result of as?
let value: Any = "Hello"
if let casted = value as? String {
text = casted
}
A conditional cast returns an optional because the cast may fail.
Solution 28: Avoid forced casts as a shortcut
let text = value as! String
will crash at runtime if value is not actually a String.
Warning: Do not add as! merely to silence the assignment error. Prefer as? when the runtime type is not guaranteed.
Solution 29: Prefer structured models over Any
You could allow mixed types using:
var data: [String: Any] = [:]
but this weakens compile-time type safety.
For structured data, prefer:
struct User { let name: String let age: Int }
Solution 30: Break complex expressions into intermediate variables
Instead of debugging a long chain all at once:
let result = users .map { $0.age } .compactMap(Int.init) .map(String.init)
split it into:
let ageTexts: [String] = users.map { user in user.age }
let ages: [Int] = ageTexts.compactMap { text in
Int(text)
}
let result: [String] = ages.map { age in
String(age)
}
This makes every type transition explicit.
If you need to assign String to Int
Do not write:
age = text
Instead:
guard let newAge = Int(text) else { return }
age = newAge
If you need to assign String? to String
Use a meaningful default:
displayName = optionalName ?? "Unknown"
or assign only when a value exists:
if let optionalName { displayName = optionalName }
If you need to assign Int? to Int
count = optionalCount ?? 0
or:
guard let optionalCount else { return }
count = optionalCount
If the error involves arrays
For:
Cannot assign value of type '[String]' to type '[Int]'
convert individual elements:
let strings = ["1", "2", "3"]
let numbers: [Int] = strings.compactMap { text in
Int(text)
}
If the error involves dictionaries
var values: [String: Int] = [:]
if let count = Int("10") {
values["count"] = count
}
If the error occurs in SwiftUI
Pay particular attention to these pairs:
- String versus Binding<String>
- Bool versus Binding<Bool>
- Int versus Binding<Int>
For example:
@State private var enabled = false
Toggle("Enabled", isOn: $enabled)
enabled is Bool, while $enabled is Binding<Bool>.
If the error occurs in Picker
SwiftUI Picker selection and tag values should use compatible types:
@State private var selected = 0
Picker("Option", selection: $selected) {
Text("One").tag(0)
Text("Two").tag(1)
}
If selected is Int but the tags are String, the generic selection types no longer match.
If the error occurs after a network request
Avoid scattering conversions between transport data and application models across your UI.
struct APIUser: Decodable { let id: String }
struct User {
let id: Int
}
func mapUser(_ response: APIUser) -> User? {
guard let id = Int(response.id) else {
return nil
}
return User(id: id)
}
This gives the rest of your app one consistent type.
If the values appear compatible but Swift still rejects the assignment
Similar-looking values can still have different concrete types:
- String and Substring
- Int and Int64
- Double and CGFloat
- User and User?
- String and Binding<String>
- Status and String
- [User] and [User]?
- Result<User, Error> and User
Read the complete types shown in Xcode rather than relying only on how the values look.
What you should avoid
Do not immediately use Any or as! just to make a “Cannot assign value of type” error disappear.
The mismatch may reveal a genuine modeling problem. Decide whether a value should be stored as String, Int, optional, enum, binding, or another model type before converting it.
Also remember that failable conversions such as Int(String), enum raw-value initialization, and as? need explicit failure handling.
Fast troubleshooting checklist
- Compare the two types shown in the diagnostic.
- Inspect the declaration of the destination property or variable.
- Check String, Int, and Double mismatches.
- Check optional versus non-optional types.
- Check array and dictionary element types.
- Check enums versus raw values.
- Check generic arguments.
- Check tuple element types.
- In SwiftUI, distinguish values from bindings.
- Convert numeric types explicitly when needed.
- Review mapping between API models and domain models.
- Break complex expressions into intermediate variables.
- Avoid using Any or forced casts as a shortcut.
Summary
Swift’s “Cannot assign value of type” error means that the value being assigned has a different type from the destination variable, property, collection, or generic storage.
Common causes include String and numeric mismatches, optional versus non-optional values, incompatible collection elements, enum raw values, generic types, and SwiftUI Binding mistakes.
Start by comparing the source and destination types in the compiler diagnostic.
Use Int() for String-to-Int conversion, String() for Int-to-String conversion, if let or guard let for optionals, and ?? when a meaningful default value exists.
In SwiftUI, remember that property and $property are different types.
Rather than weakening type safety with Any or forced casts, choose the type that correctly represents the data and perform explicit, safe conversion at the appropriate boundary.
