什么是Swift中等同于TypeScript联合类型的内容?

5
我希望在Swift上创建类似这样的东西,用于Alamofire json解析。
interface Question {
  value: string;
  data: [string]
}

interface Advice {
  type: string;
  data: { value: string }
}

interface CurrentItem {
  type: string;
  data: Advice | Question | string
}

1
“value”可以是“Type1”,“Type2”或“Type3”类型的意思是什么? - Larme
值可以是Type1、Type2或Type3中的一种。 - Igor Doroshenko
我只有一个点,它可以返回例如建议、问题或字符串。 - Igor Doroshenko
@IgorDoroshenko,你的设计有些不太好。TypeScript 的类型非常宽松,因为它基于 JavaScript。另一方面,Swift 对类型非常严格。通常来说,严格的类型更好,因为它促进了更好的设计模式。从函数中返回 3 种不同的对象类型通常是一个非常糟糕的想法。也许使用带有关联值的枚举类型会更合适。 - Sulthan
1
@Alexander TS联合类型是一种和类型,因为您必须使用模式匹配来区分类型。Swift枚举作为一种和类型,是TS联合类型的最接近等价物。协议及其符合实现是多态类型,它们不是联合类型。 - kierans
显示剩余4条评论
2个回答

12

使用关联值 (associated values) 的枚举类型 (enum) 来表示不同的可能性:

enum Data {
  case advice (Advice)
  case question (Question)
  case string (String)
}

您可以将当前项目作为结构体创建

struct CurrentItem {
  type: String
  data: Data
}

如果你要从 JSON 进行解码,你需要将结构体符合 Decodable 协议并编写自定义的 init(from decoder: Decoder) 方法,该方法检查提供的数据,然后创建 Data 枚举的适当实例。


1
我发现了一个很棒的应用程序,可以在ts上创建swift界面。 https://app.quicktype.io/ - Igor Doroshenko

2

我认为在Swift中处理这样的联合类型的方式是使用协议。

struct Test {
    var value: MyProtocol
}

(Note我使用了struct,但它可以是您需要的任何类型的对象。)
其中Type1Type2Type3符合某个共享协议。无论是通过构造还是可以扩展以采用该协议。这是有利的,因为您的对象不必局限于三种类型之一并分别处理每种类型,而是不必了解其所需支持的每种类型的内部工作原理。
MyProtocol看起来会像这样:
protocol MyProtocol {
    var myValue: Bar { get set }
    func myMethod(_ foo: Foo) -> SomeType
}

假设您想要扩展Type1以采用MyProtocol

extension Type1: MyProtocol {
    var myValue: Bar { foo }
    func myMethod(_ foo: Foo) -> SomeType { bar }
}

另外,Swift有许多内置协议,可能已经在你的三种类型之间共享。

请注意,您可以声明符合多个类型的联合类型,使用&,但是Swift没有相应的“此类型或该类型”的想法。

请注意,如果您的协议具有Self或关联类型要求,则无法像上面所示那样用作通用约束。

Swift语言指南中了解更多关于协议的内容。

然而,如果您的三种类型没有任何共同点,Swift还有Any类型,在您的代码中,您可以根据需要使用条件转换测试每种类型:

struct Test { 
    var value: Any
    func doSomething() {
        if let value = value as? Type1 {
            doTheThing()
        } // etc.
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接