Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I define an extension to CollectionType so that its methods are available to dictionaries?

Tags:

swift

I was recently able to change an extension from:

extension Array where Element: Encodable { ... }

to:

extension CollectionType where Generator.Element: Encodable { ... }

in order to later be able to apply type constraints with CollectionType and Encodable in a different extension.

Now I'm trying to do the same thing with Dictionary, changing:

extension Dictionary where Key: StringLiteralConvertible, Value: Encodable { ... }

to:

extension CollectionType where Generator.Element == (Key: StringLiteralConvertible, Value: Encodable) { ... }

However, the latter appears not to be a valid substitute for the Dictionary type, since now methods defined within the extension can't be called on dictionaries.

How can I define an extension to CollectionType (or maybe SequenceType) so that its methods are available to dictionaries?


Update

I wanted to note that I've tried adding type constraints as follows, without success:

extension CollectionType where Self: protocol<Indexable, SequenceType, DictionaryLiteralConvertible>, Self.Key: protocol<Hashable, StringLiteralConvertible>, Self.Value: Encodable, Self.Generator.Element == (Key: StringLiteralConvertible, Value: Encodable) { ... }

Update 2

Since user2194039 asked – I'd prefer not to have to do this and keep the extensions to Array and Dictionary.

However, I also need to write extensions for the Optional variants. My understanding is that due to their use of generics, it's not possible to write a type constraint for Optional that constrains it to Array or Dictionary.

like image 728
Paul Young Avatar asked Oct 20 '22 05:10

Paul Young


2 Answers

This works for my current use case:

extension CollectionType where Self: DictionaryLiteralConvertible, Self.Key: StringLiteralConvertible, Self.Value: Encodable, Generator.Element == (Self.Key, Self.Value) { ... }
like image 111
Paul Young Avatar answered Nov 23 '22 13:11

Paul Young


Thanks for posting your solution did help a lot, I converted your solution to swift 3 but don't know why it was not working for me, so I want to post my solution maybe can help someone else.

extension Collection where Self: ExpressibleByDictionaryLiteral, Self.Key: ExpressibleByStringLiteral, Self.Value: ExpressibleByStringLiteral, Iterator.Element == (key: Self.Key, value: Self.Value) { ... }

I was also able to constraint the collection to a specific type:

extension Collection where Self: ExpressibleByDictionaryLiteral, Self.Key == String, Self.Value == Array<String>, Iterator.Element == (key: Self.Key, value: Self.Value)

The key was Iterator.Element == (key: Self.Key, value: Self.Value)

Thanks for your help

like image 33
Serluca Avatar answered Nov 23 '22 13:11

Serluca