Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

Swift Dictionary

  1. Home
  2. Swift Dictionary
  3. Generic Types / where Clause

Generic Types / where Clause

Since: Swift 1.0(2014)

A generic type in Swift is a struct, class, or enum that has one or more type parameters. The following covers advanced usage — make sure you understand the basics of generics before reading on.

Using a where clause, you can express complex constraints on those type parameters.

Syntax

// Generic struct
struct TypeName<T> {
    var items: [T]
    mutating func push(_ item: T) { items.append(item) }
    mutating func pop() -> T? { return items.popLast() }
}

// Generic function with a where clause
func functionName<T, U>(_ t: T, _ u: U) where T: Equatable, U: Hashable {
    // body
}

// Extension with a where clause (conditional extension)
extension Array where Element: Numeric {
    var sum: Element { return reduce(0, +) }
}

Syntax reference

SyntaxDescription
struct Name<T> { }Defines a generic structure with a type parameter.
where T: ProtocolConstrains a type parameter to conform to a protocol.
where T == URequires that two type parameters are the same type.
associatedtypeDefines a type placeholder used inside a protocol.
extension Type<T> where T: ConstraintDefines an extension that is only available when the given condition is met.

Sample code

sample_generic_type_where.swift
// A generic stack
struct Stack<T> {
    private var items: [T] = []

    mutating func push(_ item: T) {
        items.append(item)
    }

    mutating func pop() -> T? {
        return items.popLast()
    }

    var top: T? { return items.last }
    var isEmpty: Bool { return items.isEmpty }
    var count: Int { return items.count }
}

var intStack = Stack<Int>()
intStack.push(1)
intStack.push(2)
intStack.push(3)
print("Stack top: \(intStack.top!)")
print("pop: \(intStack.pop()!)")

// A protocol with an associated type
protocol Container {
    associatedtype Item
    mutating func append(_ item: Item)
    var count: Int { get }
    subscript(i: Int) -> Item { get }
}

// Constraining the associated type with a where clause
func compareContainers<C1, C2>(_ c1: C1, _ c2: C2) -> Bool
    where C1: Container, C2: Container, C1.Item == C2.Item, C1.Item: Equatable {
        guard c1.count == c2.count else { return false }
        for i in 0..<c1.count {
            if c1[i] != c2[i] { return false }
        }
        return true
}

// Conditional extension
extension Stack: Equatable where T: Equatable {
    static func == (lhs: Stack, rhs: Stack) -> Bool {
        return lhs.items == rhs.items
    }
}

let stack1 = Stack<Int>()
let stack2 = Stack<Int>()
print("Empty stack comparison: \(stack1 == stack2)")

Running the above produces the following output:

swift generic_type_where.swift
Stack top: 3
pop: 3
Empty stack comparison: true

Overview

Generic types let you define reusable data structures that work with different types. Swift's standard library types — Array, Dictionary, and Optional — are all implemented as generic types.

Unlike the simple : constraint syntax, a where clause can express multiple constraints and relationships between types (such as T.Element == U). Protocols with associated types cannot be used as regular types; they can only appear inside generic constraints (where clauses). Starting with Swift 5.7, you can use them as existentials with the any ProtocolName syntax.

For details on some and any, see some / any / opaque type.

If you find any errors or copyright issues, please .