Search code examples
swiftclasstypesprotocols

Swift Type Aliasing like C# possible?


I want to have the following types:

  • Renderable = Protocol/Interface with function render()
  • Bag<T> = Renderable, OrderedDictionary<String, T> where T = Renderable
  • Bag = Bag<Renderable> (shorthand without T-type specification, just assuming it is Renderable)

This will ensure, I can render() everything. And in Bag I can store anything Renderable, either providing the specific types or not.

The C# version looks like this:

public class Bag : Bag<object> {}
public class Bag<T> : Dictionary<string, T> {
    public override string ToString() => ToString("");      
    public string ToString(string separator) => string.Join(separator, this.Values);
}

Trying to translate this into Swift:

public protocol Renderable {
    func render() -> String
}
import OrderedCollections

public typealias Bag<T> = OrderedDictionary<String, T> where T: Renderable

extension Bag: Renderable {
    public func render() -> String {
        render(separator: "")
    }
    
    public func render(separator: String = "") -> String {
        if count == 0 { return ""}
        return map {
            $0.value.render()  <-- compilers says: value has no member "render"
        }.joined(separator: separator)
    }
}

Q1: Why does Swift think, $0.value, which is a T, which is constraint to Renderable has no function render()? Q2: How would I define a simple type Bag like the C# version, like

public typealias Bag = Bag<Renderable>

Solution

  • Since you want to store any type that conforms to Renderable in your dictionary you can simply skip the generic T in the typealias and directly use the protocol instead

    public typealias Bag = OrderedDictionary<String, Renderable>