← Back to Swift Course | Chapter 12: Generics & Advanced Types | Lesson 3 of 7

Type Constraints

A type constraint is a rule that says a generic placeholder can only be filled in by types that meet a certain requirement, like "must be comparable."
Syntax
swift
func functionName<T: ProtocolName>(_ items: [T]) -> T? {
    // can use what ProtocolName provides, e.g. < for Comparable
}

Constraining to Comparable

Adding : Comparable to a generic placeholder allows the function to use comparison operators like < and >, which aren't guaranteed on an unconstrained type.

Example: Constraining to Comparable

markup
func findLargest<T: Comparable>(_ items: [T]) -> T? {
    guard var largest = items.first else { return nil }
    // Loop over `items where item > largest`, binding each item to `item`
    for item in items where item > largest {
        largest = item
    }
    // Return `largest` from this function
    return largest
}
// Print `findLargest([3, 7, 2, 9, 4]) as Any` to the console
print(findLargest([3, 7, 2, 9, 4]) as Any)
// Print `findLargest(["banana", "apple", "cherry"]) as Any` to the console
print(findLargest(["banana", "apple", "cherry"]) as Any)

Constraining to a Custom Protocol

A generic placeholder can also be constrained to any custom protocol, requiring conforming types to implement its specific requirements.

Example: Constraining to a Custom Protocol

markup
// Define a protocol `Summable` describing required behavior
protocol Summable {
    static func + (lhs: Self, rhs: Self) -> Self
    static var zero: Self { get }
}
// Extend `Int` with additional functionality
extension Int: Summable {
    static var zero: Int { 0 }
}
func total<T: Summable>(_ items: [T]) -> T {
    // Declare a mutable variable `result`, initialized to `T.zero`
    var result = T.zero
    // Loop over `items`, binding each item to `item`
    for item in items {
        result = result + item
    }
    // Return `result` from this function
    return result
}
// Print `total([1, 2, 3, 4])` to the console
print(total([1, 2, 3, 4]))
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Writing a generic function that uses < or == on its placeholder type without constraining it to Comparable or Equatable first -- the compiler will reject unconstrained comparisons.
  2. Confusing a class-inheritance constraint (T: SomeClass) with a protocol constraint (T: SomeProtocol); both use the same colon syntax but mean different things.
  3. Over-constraining a generic function with requirements it doesn't actually need, unnecessarily limiting what types can be used.
Chapter Summary
  • A constraint restricts a generic placeholder to types conforming to a protocol or inheriting a class.
  • Constraints are written after the placeholder name with a colon, like <T: Comparable>.
  • Constraints let you use operations (like < or ==) that aren't available on every possible type.
  • Multiple constraints can be combined using & or a where clause.
🔒

Chapter Quiz — Complete all 7 topics to unlock

0/7 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.