We seem to be talking at cross purposes here.
You cite this code:
public struct Foo<E: Hashable>: Equatable, Collection
{
public typealias Element = E
private var array: [Element]
…
}
… where the generic struct Foo<E : Hashable> has a placeholder E (which is required to implement Hashable, in order that any type that is used for E will be compatible with the Element parameter declared in the Collection protocol); and the struct Foo<E> also is required to implement the Collection (generic) protocol.
The typealias Element = E line is there to bind the E parameter of the generic struct to the Element associatedtype from the (generic) Collection protocol; nothing more nothing less. This is the reason I gave you my example of using type aliases to help the compiler to give you the missing "abstract" methods that are needed to fully implement the Collection protocol.
On the other hand, your code:
public struct Foo<Element: Hashable>
{
private var array: [Element]
…
}
… has nothing to do with implementing a protocol; it is simply a generic struct with a placeholder parameter called Element, which is required to implement Hashable.
This time, the struct simply contains an array of whatever Element is used as when you use Foo<Element>. There is no need for a typealias because there is nothing to bind the Element placeholder to; it serves the same purpose as E in the first example, but without the bit where the struct implements Collection.
I must admit to being puzzled about what @Airspeed Velocity's code:
struct S<T> { typealias U = T }
typealias TA = S<Int>
let x: TA.T // 'T' is not a member type of 'TA' (aka 'S<Int>')
let y: TA.U
… is intended to achieve. Why would you want a typealias U for the type T that is already known and available? In many, many years of programming generics, it something I've not yet come across, unless it's another way of writing something else I might have used in C# generics.
Let me replace Swift's own Collection protocol with one just for you Dalija:
protocol DalijaCollection
{
associatedtype ItemType : Hashable // placeholder - does the same as Element from Collection
func append(item: ItemType)
func remove(item: ItemType)
var count: Int { get }
subscript(index: Int) -> ItemType { get }
}
class Stack<itemT : Hashable> : DalijaCollection
{
typealias ItemType = itemT // not needed once all the members of DalijaConnection have been implemented
lazy var items: [itemT] = .init()
func push(item: itemT)
{
items.append(item)
}
func pop() -> itemT?
{
guard let result = items.last,
let lastIndex = items.lastIndex(of: result) else
{
return nil
}
items.remove(at: lastIndex)
return result
}
func append(item: itemT)
{
items.append(item)
}
func remove(item: itemT)
{
guard let index = items.index(of: item) else
{
fatalError("item not found")
}
items.remove(at: index)
}
var count: Int
{
return items.count
}
subscript(index: Int) -> itemT
{
return items[index]
}
}
With the DalijaCollection version, you can do this:
while stack.count > 0
{
print(stack.pop())
}
// or
for i in 0..<stack.count
{
print(stack[i])
}
… Swift's Collection protocol also allows you to use the for…in construct like this:
{
for item in stack
{
print(item)
}
}
… as well as a whole load more.