Swift Type Casting
Type Casting consists of two things
- Type Checking
- Changing the Type
- is an operator is used to check the type of an instance type?
- as an operator is used to casting the instance to another type.
Swift Type Checking
Swift gives a lot of priority to the readability of the code. No wonder to check whether an instance belongs to a certain type, we use the is the keyword. For Example, the following code snippet would always print false.
var aString = "BaluTutorial.com" print(aString.self is Int) // false
Let’s do the type checking in the class and its subclasses. For that, we’ve created the following three classes.
import Foundation class University { var university: String init(university: String) { self.university = university } } class Discipline : University { var discipline: String init(university: String, discipline: String) { self.discipline = discipline super.init(university: university) } } class Student : University { var student: String init(student: String, university: String) { self.student = student super.init(university: university) } }
In the following sections, we’ll be looking at Upcasting and Downcasting.
Swift Upcasting
Let’s create an object of each of the classes and combine them in an Array. Our goal is to know thy type!
var arrayObject = [University(university: "IIT"), Discipline(university: "IIT",discipline: "Computer Science"), Student(student: "Balu Naik",university: "IIT")] print(arrayObject is [Student]) //false print(arrayObject is [Discipline]) //false print(arrayObject is [University]) //true
The array is of the type University. All the subclasses are always implicitly upcasted to the parent class. In the above code, the Swift Type Checker automatically determines the common superclass of the classes and sets the type to it.
type(of:) can be used to determine the type of any variable/constant.
var university = University(university: "IIT") var student = Student(student: "BaluNaik",university: "IIT") var discipline = Discipline(university: "IIT",discipline: "Computer Science") print(student is University) //true print(discipline is University) //true print(university is Student) //false print(university is Discipline) //false
Protocols are types Hence type checking and casting work the same way on them. The following code prints true.
protocol SomeProtocol { init(str: String) } class SomeClass : SomeProtocol { required init(str: String) { } } var myObject = SomeClass(str: "BaluTutorial.com") print(myObject is SomeProtocol) //true
Swift Downcasting
For downcasting a superclass to the subclass, we use the operator as.
- as has two variants, as? and as! to handle scenarios when the downcasting fails.
- as is typically used for basic conversions.
- as? would return an optional value if the downcast succeeds and nil when it doesn’t.
- as! force unwraps the value. Should be used only when you’re absolutely sure that the downcast won’t fail. Otherwise, it’ll lead to a runtime crash.
//Double to float let floatValue = 2.35661312312312 as Float print(floatValue) //prints 2.356613 let compilerError = 0.0 as Int //Compiler error let crashes = 0.0 as! Int //Runtime crash
Let’s look at the class hierarchy again. Let’s try to downcast the array elements to the subclass types now.
var arrayObject = [University(university: "IIT"), Discipline(university: "MIT",discipline: "Computer Science"), Student(student: "Balu",university: "BITS"), Student(student: "Naik",university: "MIT")] for item in arrayObject { if let obj = item as? Student { print("Students Detail: \(obj.student), \(obj.university)") } else if let obj = item as? Discipline { print("Discipline Details: \(obj.discipline), \(obj.university)") } }
We downcast the type University to the subclass types. Following results get printed in the console.

We’ve used if let statements to unwrap the optional gracefully.
Any and AnyObject
As per the Apple Docs:
- Any can represent an instance of any type at all, including function types.
- AnyObject can represent an instance of any class type.
AnyObject can be a part of Any type. Inside an AnyObject array, to set value types, we need to typecast them to the AnyObject using as an operator.
import Foundation class AClass { var name = "Balu Naik" } func printHello() { print("Hello Balututorial.com") } var anyType: [Any] = [1, "Hey", true, 1.25, AClass(), printHello()] var anyObjectType: [AnyObject] = [AClass(), 1 as AnyObject, "Hello" as AnyObject] print(anyType) print(anyObjectType) for item in anyType { if let obj = item as? AClass { print("Class AClass property name is: \(obj.name)") } } for item in anyObjectType { if let obj = item as? String { print("String type: \(type(of: obj))") } }

The function that’s present in the anyType array, gets printed on the array’s declaration. Notice that for anyObjectType, the string gets printed without double-quotes. Besides AnyObject allows object types only. String and Int are value types.
Then how is it working?
On typecasting the string and int as AnyObject they both get converted into NSString and NSNumber class types which are not value types. Hence it is possible to set String, Int in AnyObject provided we use the as operator correctly.