john doe
john doe

Reputation: 9660

Evaluating the Objects Type in Swift

I have the following code in Swift:

 func foo()
    {
        let name = "Hello World"

        if name is String
        {

        }
        else
        {

        }
    }


I get the error: 'is' test is always true 

I know it is always true! But why is this an error?

Upvotes: 3

Views: 319

Answers (3)

Alex Wayne
Alex Wayne

Reputation: 186994

Swift compiles your declaration, through type inference, as this:

let name: String = "Hello World"
if name is String { ...

You can't test the type of a variable against the type it was declared as because that will ALWAYS be true, and that fact is evident at compile time. In this case, you know for sure that name is a String. The static typing of Swift means you should never need to do this test. You can always assume that a variable of type String is a String.

To use is the type of the var must be castable, but not identical to, the type you are comparing it to. So this will compile if name is an ambiguous type that could be String or could be something else entirely. Then the test actually makes sense.

let name: AnyObject = "Hello World"
if name is String {
  println("name is a string")
} else {
  println("name is NOT a string :(")
}

Some more examples of when you can is and when you can't.

// Good
// AnyObject can be casted to String
let name: AnyObject = "Hello World"
if name is String {}

// Also good
// UInt32 can be casted to Int
let num: UInt32 = 123
if num is Int {}

// error: 'String' is not a subtype of 'Int'
// Int cannot be casted to String, this will NEVER be true
let name: Int = 123
if name is String {}

// error: 'is' test is always true
// String will always be string, this will ALWAYS be true
let name: String = "Hello"
if name is String {}

Upvotes: 4

Antonio
Antonio

Reputation: 72750

Variables in swift are (very) strongly typed. If you write something like that, most likely you are doing something wrong in your code.

I appreciate that the compiler outputs that as an error - otherwise I might thing the else branch can be executed under some conditions.

Data types and structures don't support inheritance, so if you declare a String variable, it cannot be anything else (besides Any and AnyObject, which are protocols though) .

If you declare a string variable :

var test: String = "test"

it can never be anything else, so this always fails:

if test is Int { // < 'Int' is not a subtype of 'String'
    ...
}

Testing if a string is a string is pointless, so the compiler considers it as an error, although maybe it's more a warning, because the code is syntactically and semantically correct.

By the way checking a data type or struct for Any and AnyObject produces the same error, so I presume the same is valid for any protocol they implement.

Upvotes: 1

vacawama
vacawama

Reputation: 154533

It's an error because Swift tries its hardest to keep you from doing useless things. Swift figures that since this test is always true, you must have intended to do something else.

Upvotes: 3

Related Questions