Search code examples
swift

When can Swift infer data types and when can it not?


I was coding below, and I wondered why I needed the extra .00 in 70_000.00. I know that if I didn't, it would be considered an integer.

protocol Building {
  var rooms: Int { get }
  var price: Double { get }
  var retailer: String { get }
}

struct House: Building {
  var rooms = 4
  var price = 70_000.00
  var retailer = "John Doe"

}

I thought that Swift could infer the data type in times like these, especially when I already told Swift that "Price" was a double.


Solution

  • From the docs:

    Type inference in Swift operates at the level of a single expression or statement. This means that all of the information needed to infer an omitted type or part of a type in an expression must be accessible from type-checking the expression or one of its subexpressions.

    In other words, for a variable declaration, type inference is exclusively local to what it sees on the right-hand side of the assignment. This is the case even if context surrounding that assignment would cause it to otherwise infer a different type. For example:

    let a = 10
    let b: Double = a / 5.0
    //              ^ cannot convert value of type 'Int' to expected argument type 'Double'
    

    Swift will never infer the type of a to be Double, because the right-hand side of the assignment is an integer literal — in which case, it decides that the most appropriate type is Int; lines before or after the assignment don't come into the picture at all.

    This is the same for var price: if you assign an integer literal, Swift will infer a type of Int; assigning a floating-point literal instead will cause it to decide that Double is the most appropriate type, which will happen to match the protocol requirement you're trying to fulfill. Alternatively, giving var price an explicit type would allow you to assign an integer literal: var price: Double = 70_000.

    Because of the potential for unexpected inference of types, some style guidelines recommend always giving instance variables explicit types, to make it very clear what the expected type should be.