Philippe Leybaert Philippe Leybaert - 1 year ago 81
Swift Question

Generic function taking a type name in Swift

In C#, it's possible to call a generic method by specifying the type:

public T f<T>()
return something as T

var x = f<string>()

Swift doesn't allow you to specialize a generic method when calling it. The compiler wants to rely on type inference, so this is not possible:

func f<T>() -> T? {
return something as T?

let x = f<String>() // not allowed in Swift

What I need is a way to pass a type to a function and that function returning an object of that type, using generics

This works, but it's not a good fit for what I want to do:

let x = f() as String?


I've probably not been very clear about what the question actually is, it's all about a simpler syntax for calling a function that returns a given type (any type).

As a simple example, let's say you have an array of Any and you create a function that returns the first element of a given type:

// returns the first element in the array of that type
func findFirst<T>(array: [Any]) -> T? {
...(implementation omitted)

You can call this function like this:

let array = [something,something,something,...]

let x = findFirst(array) as String?

That's pretty simple, but what if the type returned is some protocol with a method and you want to call the method on the returned object:

(findFirst(array) as MyProtocol?)?.SomeMethodInMyProtocol()
(findFirst(array) as OtherProtocol?)?.SomeMethodInOtherProtocol()

That syntax is just awkward. In C# (which is just as strongly typed as Swift), you can do this:


Sadly, that's not possible in Swift.

So the question is: is there a way to accomplish this with a cleaner (less awkward) syntax.

Answer Source

Unfortunately, you cannot explicitly define the type of a generic function (by using the <...> syntax on it). However, you can provide your type as a generic argument to the function in order to allow Swift to infer it, as Roman has said. For your specific example, you'll want your function to look something like this:

func f<T>(array:[Any], type:T.Type) -> T? {
    return array.first as? T

You can then do your conditional downcast of whatever type to want to T – and will return an optional result of this downcast.

You can use it like so:

protocol SomeProtocol {
    func doSomething()

extension String:SomeProtocol {
    func doSomething() {

// "success" gets printed to the console in this case,
// as the first element conforms to SomeProtocol
f(["foo", "bar"], type:SomeProtocol.self)?.doSomething()

// "success" doesn't get printed to the console in this case
f([0, 1], type:SomeProtocol.self)?.doSomething()

Note that you have to pass in the meta-type of your given protocol through using .self. Perhaps not a slick as the syntax you were aiming for, but I think it's about as good as you're going to get to it.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download