I’ve implemented a Swift GraphQL web service using Vapor and Graphiti which has a custom schema for ClosedRange<Dobule>
which is encoded into an array of two Doubles [5, 8]
.
On the client side I’m using Apollo for iOS and have tried to implement the custom scehma decoding by conforming ClosedRange<Dobule>
to CustomScalarType
but I get the error:
Conditional conformance of type ‘ClosedRange’ to protocol ‘CustomScalarType’ does not imply conformance to inherited protocol ‘AnyHashableConvertible’
// @generated
// This file was automatically generated and should not be edited.
import ApolloAPI
import Foundation
public extension ClientAPI {
typealias DoubleClosedRange = ClosedRange<Double>
}
extension ClosedRange<Double>: CustomScalarType {
public init(_jsonValue value: JSONValue) throws {
guard let elements = value as? [Double] else {
throw JSONDecodingError.couldNotConvert(value: value, to: [Double].self)
}
self = ClosedRange(uncheckedBounds: (lower: elements[0], upper: elements[1]))
}
public var _jsonValue: JSONValue {
[lowerBound, upperBound]
}
}
I’m not sure I really understand the error, I’ve created conformance for other Foundation types like URL
in the same way without issues.
Hi @cameroncooke
Being generic ClosedRange
itself has no unit type, it’s Bound
that does instead. I believe it’s this that is tripping you up and you’ll need to provide conformance for all the required protocols narrowing the conformance to Double
.
This builds but there might be some additional work needed in some of the empty extensions:
extension ClosedRange: AnyHashableConvertible where Bound == Double {}
extension ClosedRange: GraphQLOperationVariableValue where Bound == Double {}
extension ClosedRange: OutputTypeConvertible where Bound == Double {}
extension ClosedRange: AnyScalarType where Bound == Double {}
extension ClosedRange: CustomScalarType where Bound == Double {}
extension ClosedRange: JSONEncodable where Bound == Double {
public var _jsonValue: JSONValue {
[lowerBound, upperBound]
}
}
extension ClosedRange: JSONDecodable where Bound == Double {
public init(_jsonValue value: JSONValue) throws {
guard let elements = value as? [Double] else {
throw JSONDecodingError.couldNotConvert(value: value, to: [Double].self)
}
self = ClosedRange(uncheckedBounds: (lower: elements[0], upper: elements[1]))
}
}
I’m not sure why extension ClosedRange: CustomScalarType where Bound == Double {..}
doesn’t work. I assume it wants you to explicitly state the conformance?
Amazing, was starting to pull my hair out, thank you so much, that works!
I did try:
extension Double: CustomScalarType {
...
}
I thought that should work but maybe my understanding of conditional conformance was flawed.
We really need an open-source package of common Swift scalars conformances like URL, Range etc. I believe the JS community has a similar package.
1 Like