Can I assign a default type to generic type T in Swift?

There's no support for default generic arguments, but you can fake it by defining the default init() on a type-constrained extension, in which case the compiler will be smart enough to use that type. E.g.:

class MyManager<T> {
    let instance: T

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

extension MyManager where T == NSObject {
    convenience init() {
        self.init(instance: NSObject())
    }
}

And now you can initialize the type with no argument and it will default to MyManager<NSObject>:

let mm1 = MyManager(instance: "Foo") // MyManager<String>
let mm2 = MyManager(instance: 1) // MyManager<Int>
let mm3 = MyManager() // MyManager<NSObject>

SwiftUI uses this technique quite a lot.


No, this currently isn't possible – although it is a part of the Generics Manifesto, so might be something that the Swift team will consider for a future version of the language.

Default generic arguments

Generic parameters could be given the ability to provide default arguments, which would be used in cases where the type argument is not specified and type inference could not determine the type argument. For example:

public final class Promise<Value, Reason=Error> { ... }

func getRandomPromise() -> Promise<Int, Error> { ... }

var p1: Promise<Int> = ... 
var p2: Promise<Int, Error> = p1     // okay: p1 and p2 have the same type Promise<Int, Error>
var p3: Promise = getRandomPromise() // p3 has type Promise<Int, Error> due to type inference

In the meantime however, a somewhat unsatisfactory compromise would be the use of a typealias:

class MyManager<T> {}

typealias MyManagerDefault = MyManager<NSObject>

let defaultManager = MyManagerDefault()

Not nearly as slick as just being able to say MyManager(), but it does show up next to MyManager in auto-complete, which is pretty handy.

Tags:

Generics

Swift