PC パソコン

How to Fix “Cannot Assign Value of Type” in Swift

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.

  1. What does “Cannot assign value of type” mean?
  2. How is this different from “Cannot convert value of type”?
  3. Typical situations where the error appears
  4. Common causes
    1. 1. Assigning String to Int
    2. 2. Assigning Int to String
    3. 3. Assigning Double to Int
    4. 4. Assigning an optional to a non-optional
    5. 5. Assigning Int(String) directly to Int storage
    6. 6. Array element types differ
    7. 7. Dictionary value types differ
    8. 8. A dictionary subscript receives the wrong value type
    9. 9. A String is assigned directly to an enum
    10. 10. Generic collection types differ
    11. 11. Result has the wrong success type
    12. 12. Tuple element types differ
    13. 13. A SwiftUI Binding is treated as a plain value
    14. 14. A plain value is used where a Binding is required
    15. 15. map returns the wrong collection element type
    16. 16. compactMap produces a different type than expected
    17. 17. API response properties have different types
    18. 18. Numeric types such as CGFloat and Double differ
    19. 19. A closure has an incompatible function type
    20. 20. Protocol or generic constraints do not allow the assignment
  5. What to check first
    1. 1. Compare the two types in the diagnostic
    2. 2. Inspect the declaration of the destination
  6. Solution 1: Convert String to Int
  7. Solution 2: Validate String-to-Int conversion with guard
  8. Solution 3: Convert Int to String
  9. Solution 4: Convert Double to Int carefully
  10. Solution 5: Convert Int to Double
  11. Solution 6: Unwrap an optional before assignment
  12. Solution 7: Use a meaningful default value
  13. Solution 8: Make the destination optional when nil is valid
  14. Solution 9: Match array element types
  15. Solution 10: Convert a String array into an Int array
  16. Solution 11: Convert an Int array into a String array
  17. Solution 12: Match dictionary value types
  18. Solution 13: Convert an enum raw value into the enum
  19. Solution 14: Convert an enum to its raw value
  20. Solution 15: Match every tuple element type
  21. Solution 16: Match Result success types
  22. Solution 17: Distinguish SwiftUI bindings from values
  23. Solution 18: Pass the correct binding to child views
  24. Solution 19: Use the wrapped value where a Binding is not required
  25. Solution 20: Convert numeric types explicitly
  26. Solution 21: Map transport models into domain models
  27. Solution 22: Match generic parameters
  28. Solution 23: Match closure function types
  29. Solution 24: Make map result types explicit
  30. Solution 25: Distinguish optional arrays from arrays
  31. Solution 26: Handle optional dictionaries explicitly
  32. Solution 27: Unwrap the result of as?
  33. Solution 28: Avoid forced casts as a shortcut
  34. Solution 29: Prefer structured models over Any
  35. Solution 30: Break complex expressions into intermediate variables
  36. If you need to assign String to Int
  37. If you need to assign String? to String
  38. If you need to assign Int? to Int
  39. If the error involves arrays
  40. If the error involves dictionaries
  41. If the error occurs in SwiftUI
  42. If the error occurs in Picker
  43. If the error occurs after a network request
  44. If the values appear compatible but Swift still rejects the assignment
  45. What you should avoid
  46. Fast troubleshooting checklist
  47. 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

  1. Compare the two types shown in the diagnostic.
  2. Inspect the declaration of the destination property or variable.
  3. Check String, Int, and Double mismatches.
  4. Check optional versus non-optional types.
  5. Check array and dictionary element types.
  6. Check enums versus raw values.
  7. Check generic arguments.
  8. Check tuple element types.
  9. In SwiftUI, distinguish values from bindings.
  10. Convert numeric types explicitly when needed.
  11. Review mapping between API models and domain models.
  12. Break complex expressions into intermediate variables.
  13. 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.