首页 > 解决方案 > 将我的类型转换为预期的参数类型

问题描述

我正在使用 Apollo Client 在 Xcode 中自动生成 graphql 类型和查询,但遇到了一个我不知道如何最好地解决的问题。TLDR 是如何允许将一个结构用作接受具有相同结构的另一种类型的函数的参数?

Apollo 为我生成了一个名为“SizeInput”的结构,如下所示:

struct SizeInput: GraphQLMapConvertible {
  public var graphQLMap: GraphQLMap
  public init(cm: Double) {
    graphQLMap = ["cm": cm]
  }
  public var cm: Double {
    get {
      return graphQLMap["cm"] as! Double
    }
    set {
      graphQLMap.updateValue(newValue, forKey: "cm")
    }
  }
}

(顺便说一句 -GraphQLMap是 的类型别名[String : JSONEncodable?]

我创建了一个Size用于我的代码的结构。我不想SizeInput在我的代码中使用 将后端与我的应用程序代码分开,这样如果后端或应用程序发生变化,事情就不会中断。

struct Size {
  let cm: Double
}

我需要运行一个SizeInput以参数为参数的 apollo 查询,我想Size从选择器填充的变量中填充该参数。虽然我知道我可以创建一个新SizeInput的 from Size,但我很想传入Size查询,因为它们本质上是相同的,只是两种不同的类型。截至目前,XCode 显然在抱怨Cannot convert value of type 'Size' to expected argument type 'SizeInput'

更重要的是我不能(不想)改变 Apollo 函数,因为它是自动生成的。所以我理想的解决方案是以某种方式进行类型转换SizeSizeInput但是如果我只是尝试执行let sizeInput = size as? SizeInputwhere sizeis a ,XCode 会抱怨Size

假设我无法修改接受参数的函数并且我无法修改SizeInput,因为两者都是自动生成的,我该如何修改Size才能将其用作SizeInput参数?

标签: swiftxcodeapollo

解决方案


Size并且SizeInput根据您的帖子是两种不同的类型,因此不能按照您的想法进行类型别名。

斯威夫特的声明参考说以下关于typealias

类型别名声明将现有类型的命名别名引入您的程序。[...]声明类型别名后,可以在程序中的任何地方使用别名名称代替现有类型。[...] 类型别名不会创建新类型;它们只是允许名称引用现有类型。

...但这不是你想要的。Size并且SizeInput在合同上相似,因为它们具有cm: Double属性,但在引擎盖下的结构不同并且不能互换使用。

无论您选择何种解决方案,您都需要做出一些权衡。我至少看到以下选项。

  • 您可以编写一个位于您的 codegen GraphQL 内容之上的层,该层提供您想要的接口(即采用 a Size)并使用它。然后将您翻译SizeSizeInput. 可以使用 Codegen。
  • Size你可以SizeInput在类型本身上提供某种类型级别的函数,Size然后在你的 GraphQL 调用站点上使用它。Codegen 也可以在这里使用。
extension Size {
   func asSizeInput() -> SizeInput {
        return SizeInput(cm: cm)
    }
}
  • 您也可以在调用站点到 GraphQL 中,只需将Size实例的cm属性传递给 的构造函数SizeInput,然后您就不会编写任何额外的代码。这是一些伪代码:
let size = Size(cm: 100)
let query = SizeInputGraphQLQuery(sizeInput: size.cm)

对于我的 $,我会选择编写尽可能少的额外代码。

YMMV


推荐阅读