SWIFT

Swift Generics: Syntax, Usage, and Examples

Swift generics let you write flexible and reusable code by allowing types to be specified later. Instead of writing separate implementations for different data types, generics let you define a single function, class, struct, or protocol that works with any type.

How to Use Generics in Swift

To define a generic function or type, use angle brackets (<T>), where T represents a placeholder type.

Generic Function

func swapValues<T>(a: inout T, b: inout T) {
    let temp = a
    a = b
    b = temp
}

var x = 5
var y = 10
swapValues(a: &x, b: &y)
print(x, y) // Output: 10 5

The T placeholder lets this function work with any type, whether it's an integer, string, or custom struct.

Generic Class

You can create a generic class to store different types while keeping your code reusable.

class Box<T> {
    var value: T

    init(value: T) {
        self.value = value
    }
}

let intBox = Box(value: 42)
let stringBox = Box(value: "Hello")

print(intBox.value)  // Output: 42
print(stringBox.value) // Output: Hello

Generic Struct

Similar to a class, a generic struct can hold any type.

struct Pair<T, U> {
    let first: T
    let second: U
}

let pair = Pair(first: "Alice", second: 30)
print(pair.first)  // Output: Alice
print(pair.second) // Output: 30

Generic Enum

You can use generics in enums, which is especially useful for type-safe APIs.

enum Result<T> {
    case success(T)
    case failure(String)
}

let successResult = Result.success(100)
let failureResult = Result.failure("Something went wrong")

When to Use Generics in Swift

Avoiding Code Duplication

Generics let you write a single, reusable function instead of separate versions for different types.

func printValue<T>(_ value: T) {
    print("Value:", value)
}

printValue(10)       // Output: Value: 10
printValue("Swift")  // Output: Value: Swift

Working with Collections

Swift generics make it possible to create flexible collection types.

struct Stack<T> {
    private var elements: [T] = []

    mutating func push(_ element: T) {
        elements.append(element)
    }

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

var intStack = Stack<Int>()
intStack.push(5)
intStack.push(10)
print(intStack.pop()!) // Output: 10

Protocols with Associated Types

Swift generics work with protocols using associated types to allow flexibility in implementation.

protocol Container {
    associatedtype Item
    mutating func add(_ item: Item)
    func count() -> Int
}

struct Bag<T>: Container {
    private var items: [T] = []

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

    func count() -> Int {
        return items.count
    }
}

var bag = Bag<String>()
bag.add("Apple")
bag.add("Banana")
print(bag.count()) // Output: 2

Examples of Generics in Swift

Generic Function with Constraints

You can constrain generics to specific types using where.

func findLargest<T: Comparable>(in array: [T]) -> T? {
    return array.max()
}

let numbers = [3, 7, 2, 9]
print(findLargest(in: numbers)!)  // Output: 9

Here, T: Comparable ensures that only types that conform to the Comparable protocol can be used.

Using Generics in Protocols

A Swift generic protocol allows flexibility while enforcing specific behavior.

protocol Identifiable {
    associatedtype ID
    var id: ID { get }
}

struct User: Identifiable {
    let id: Int
}

let user = User(id: 101)
print(user.id) // Output: 101

Generic Type Alias

A generic type alias provides a shorthand for commonly used generic types.

typealias StringDictionary<T> = Dictionary<String, T>

let userAges: StringDictionary<Int> = ["Alice": 30, "Bob": 25]
print(userAges["Alice"]!) // Output: 30

Learn More About Generics in Swift

Generic Parameters vs. Associated Types

  • A generic parameter (<T>) is defined in functions, structs, and classes.
  • An associated type (associatedtype) is used in protocols to allow type flexibility.

Generic Constraints

You can use where to constrain a generic to certain types or protocols.

func printIfEqual<T: Equatable>(_ a: T, _ b: T) {
    if a == b {
        print("Equal")
    } else {
        print("Not equal")
    }
}

printIfEqual(5, 5)  // Output: Equal
printIfEqual("Hi", "Hello")  // Output: Not equal

Generic Functions with Multiple Parameters

You can use multiple generic types to handle different kinds of data.

func combine<A, B>(_ a: A, _ b: B) -> String {
    return "\(a) and \(b)"
}

print(combine(5, "Apples"))  // Output: 5 and Apples

Extending Generic Types

You can extend generic types to add extra functionality.

extension Stack {
    func peek() -> T? {
        return elements.last
    }
}

var numberStack = Stack<Int>()
numberStack.push(20)
print(numberStack.peek()!) // Output: 20

Optional Generics

A Swift optional generic lets you work with optional types in generics.

func unwrap<T>(_ value: T?) -> T {
    return value ?? fatalError("Unexpected nil value")
}

let number: Int? = 42
print(unwrap(number)) // Output: 42

Generic Properties

A generic property allows you to define a property with any type.

struct Wrapper<T> {
    var value: T
}

let wrappedInt = Wrapper(value: 99)
let wrappedString = Wrapper(value: "Swift")
print(wrappedInt.value)  // Output: 99
print(wrappedString.value)  // Output: Swift

Using Generics in Arrays

A Swift generic array allows type safety while storing different objects of the same type.

func printArray<T>(items: [T]) {
    for item in items {
        print(item)
    }
}

printArray(items: [1, 2, 3])
printArray(items: ["Swift", "Generics"])

Best Practices for Using Generics in Swift

  • Use generics when writing reusable, type-safe code.
  • Avoid overcomplicating code with excessive generic constraints.
  • Use where clauses for precise type restrictions.
  • When working with protocols, prefer associated types over generic parameters when flexibility is needed.
  • Extend generic types to add additional functionality instead of modifying existing generic structures.
Learn to Code in Swift for Free
Start learning now
button icon
To advance beyond this tutorial and learn Swift by doing, try the interactive experience of Mimo. Whether you're starting from scratch or brushing up your coding skills, Mimo helps you take your coding journey above and beyond.

Sign up or download Mimo from the App Store or Google Play to enhance your programming skills and prepare for a career in tech.

You can code, too.

© 2025 Mimo GmbH