# Multiple Types

**URL:** <https://forums.swift.org/t/multiple-types/65023>\
**Category:** Pitches\
**Created:** [May 17, 2023, 12:48am UTC](https://forums.swift.org/t/multiple-types/65023 "2023-05-17T00:48:56Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![AlexanderM](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/alexanderm/32/9781_2.png) [@AlexanderM](https://forums.swift.org/u/AlexanderM)\
**Post date:** [May 24, 2023, 3:53pm UTC](https://forums.swift.org/t/multiple-types/65023/41 "2023-05-24T15:53:16Z")

</div>

I think we're talking about different things.

The original quote of mine was:

> [@AlexanderM](#):
>
> Yep. It's a nice little emergent feature of the enum-based design.

Here, the "nice little emergent feature" I'm referring to is the ability to Optionals to compose into nested optionals (`Optional.some(Optional.some(something))`), and its utility in modelling the distinction between "missing" and "present but nil".

From what I understood of your original response, you're suggesting that type unions (or "non-nominal enums") could also do that, but I just don't see how.

---

<div class="post-metadata">

**Author:** ![allevato](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/allevato/32/385_2.png) [@allevato](https://forums.swift.org/u/allevato)\
**Post date:** [May 24, 2023, 4:20pm UTC](https://forums.swift.org/t/multiple-types/65023/42 "2023-05-24T16:20:18Z")

</div>

You would have to forbid associativity of `|` in order to achieve that result. Mathematically `(T | Nil) | Nil` is equivalent to `T | Nil | Nil` which is equivalent to `T | Nil`, but what you're really trying to express with `(T | Nil) | Nil` is that `(T | Nil)` is the `.0` element and `Nil` is the `.1` element of this anonymous thing.

---

<div class="post-metadata">

**Author:** ![sspringer](https://avatars.discourse-cdn.com/v4/letter/s/e9c0ed/32.png) [@sspringer](https://forums.swift.org/u/sspringer)\
**Post date:** [May 25, 2023, 1:24am UTC](https://forums.swift.org/t/multiple-types/65023/43 "2023-05-25T01:24:53Z")

</div>

A use case for union types: I am using a result builder which accepts (for good reason) very different types as the content [of an XML element](https://github.com/stefanspringer1/SwiftXML):

```plaintext
let element = XElement("paragraph") {
    "Hello "
    XElement("bold") { "world!" }
    " "
    otherParagraph.content
}

```

I am [using a protocol to specify what is allowed as content](https://github.com/stefanspringer1/SwiftXML/blob/d02537d9df4cd164f9de4badcec673a91c9bbbf4/Sources/SwiftXML/XML/Nodes.swift#L1094), but then I have to use a switch statement [where I have to handle all cases and be careful not forget a case](https://github.com/stefanspringer1/SwiftXML/blob/d02537d9df4cd164f9de4badcec673a91c9bbbf4/Sources/SwiftXML/XML/Nodes.swift#L1251).

Enums won‘t help because they do not allow the easy syntax above.

**Update:** I actually think I would like to have enums with some syntax trick.

---

<div class="post-metadata">

**Author:** ![sveinhal](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/sveinhal/32/3992_2.png) [@sveinhal](https://forums.swift.org/u/sveinhal)\
**Post date:** [May 25, 2023, 7:23am UTC](https://forums.swift.org/t/multiple-types/65023/44 "2023-05-25T07:23:03Z")

</div>

> [@AlexanderM](#):
>
> Here, the "nice little emergent feature" I'm referring to is the ability to Optionals to compose into nested optionals (`Optional.some(Optional.some(something))`), and its utility in modelling the distinction between "missing" and "present but nil".
> 
> From what I understood of your original response, you're suggesting that type unions (or "non-nominal enums") could also do that, but I just don't see how.

No problems:

```swift
((String | none) | none)

```

I'm suggesting that this _is_ enums, but without a name. A suggested spelling:

```swift
(first | second)
// enum AnonymousEnumWithoutAssoicatedValues {
// case first, second
// }

(first: Type | second)
// enum AnonymousEnumWithAssociatedValues {
// case first(Type)
// case second
// }

(Type | AnotherType)
// enum AnonymousEnumWithoutLabels {
// case 0(Type)
// case 1(AnotherType)
// }

(Type | (AnotherType | none))
// enum NestedAnonymousEnum {
// case 0(Type)
// case 1(Nested)
//    
// enum Nested {
// case 0(AnotherType)
// case none
// }
// }

```

But I can also envision other spellings.

However, the feature set it the same as for enums, except that they cannot be extended or have non-case members — just like unnamed tuples correlate to nominal structs without extensions, etc.

---

<div class="post-metadata">

**Author:** ![bbrk24](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bbrk24/32/27370_2.png) [@bbrk24](https://forums.swift.org/u/bbrk24)\
**Post date:** [May 25, 2023, 3:06pm UTC](https://forums.swift.org/t/multiple-types/65023/45 "2023-05-25T15:06:27Z")

</div>

> [@sspringer](#):
>
> I am [using a protocol to specify what is allowed as content](https://github.com/stefanspringer1/SwiftXML/blob/d02537d9df4cd164f9de4badcec673a91c9bbbf4/Sources/SwiftXML/XML/Nodes.swift#L1094), but then I have to use a switch statement [where I have to handle all cases and be careful not forget a case](https://github.com/stefanspringer1/SwiftXML/blob/d02537d9df4cd164f9de4badcec673a91c9bbbf4/Sources/SwiftXML/XML/Nodes.swift#L1251).

Is there a reason you can’t have a custom type that’s `ExpressibleByStringLiteral`?

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [May 25, 2023, 3:28pm UTC](https://forums.swift.org/t/multiple-types/65023/46 "2023-05-25T15:28:13Z")

</div>

> [@sveinhal](#):
>
> ```swift
> (first | second)
> // enum AnonymousEnumWithoutAssoicatedValues {
> // case first, second
> // }
> 
> (Type | AnotherType)
> // enum AnonymousEnumWithoutLabels {
> // case 0(Type)
> // case 1(AnotherType)
> // }
> 
> ```

How would compiler know if `second` is a case and `AnotherType` is a type? Do you suggest to do a lookup and if the type is found then it's a type? I don't think we have precedents like that, so I guess we'd like to have some different spelling to distinguish these two cases, bike shedding:

```swift
(:Type | :AnotherType)
(_:Type | _:AnotherType)
(0:Type | 1:AnotherType)

```

or the other way around:

```swift
(case first, second)

```

---

<div class="post-metadata">

**Author:** ![sveinhal](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/sveinhal/32/3992_2.png) [@sveinhal](https://forums.swift.org/u/sveinhal)\
**Post date:** [May 25, 2023, 3:41pm UTC](https://forums.swift.org/t/multiple-types/65023/47 "2023-05-25T15:41:00Z")

</div>

> [@tera](#):
>
> How would compiler know if `second` is a case and `AnotherType` is a type?

Sure, the spelling probably has shortcomings. I just wanted to explain how a non-nominal enum is both useful, would fill a gap, and could work as a kind of union type. But I'm sure the spelling has room for improvements.

---

<div class="post-metadata">

**Author:** ![ensan-hcl](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ensan-hcl/32/15186_2.png) [@ensan-hcl](https://forums.swift.org/u/ensan-hcl)\
**Post date:** [May 25, 2023, 3:43pm UTC](https://forums.swift.org/t/multiple-types/65023/48 "2023-05-25T15:43:47Z")

</div>

I'd just like to share my bike-shedding;

Since this is anonymous sum type in contrast to anonymous product types (tuples), we can use brackets like syntax, so that we can have analogous syntax. If you use `|` as bracket, then you can write something like this.

```swift
// equal to enum {case 0(T), 1(U), 2(V)}
// like (T, U, V) is struct {var 0: T, 1: U, 2: V}
|T, U, V|  
// equal to enum {case first(T), second(U)}
// like (first: T, second: U) is struct {var first: T, second: U}
|first: T, second: U|
// enum {} and can be alias for `Never`
// like () is `Void`
||

// unanalogous but equal to enum {case none, some(T)}
|none:, some: T|

```

And this can be naturally extended for variadic generics;

```swift
|repeat each T|

```

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [May 25, 2023, 4:47pm UTC](https://forums.swift.org/t/multiple-types/65023/49 "2023-05-25T16:47:46Z")

</div>

Another bikeshedding attempt:

```swift
(nope() | opacity(Float) | Color | rgb(Int, Int, Int))

```

or something else for outer brackets and inner separator.  
The idea is to use empty parens to denote cases without associated types (like `nope()` above) and use bare name to denote types (like `Color` above).

use site usage:

```swift
func foo(_ v: (nope() | opacity(Float) | Color | rgb(Int, Int, Int))) {
    switch v {
        case .nope: // or case .nope():
        case let .opacity(value): // or case .opacity(let value):
        case let value as Color:
        case let .rgb(r, g, b): // or case .rgb(let r, let g, let b):
    }
}

```

---

<div class="post-metadata">

**Author:** ![mayoff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mayoff/32/613_2.png) [@mayoff](https://forums.swift.org/u/mayoff)\
**Post date:** [May 25, 2023, 4:55pm UTC](https://forums.swift.org/t/multiple-types/65023/50 "2023-05-25T16:55:25Z")

</div>

Another possible solution in your case is to add a `buildExpression` method to your `resultBuilder` for each acceptable type.

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [May 25, 2023, 7:32pm UTC](https://forums.swift.org/t/multiple-types/65023/51 "2023-05-25T19:32:53Z")

</div>

> [@AlexanderM](#):
>
> Could someone please steelman the case for when this might be useful, that wouldn't be better expressed with protocols?
> 
> The original example of `func doSomething() -> String || Int` isn't particularly compelling, without a better understanding of what `doSomething` might be that's reasonably implemented by returning a string or integer.

right now in some code that deals with the swift `@available` mixin, i have three “union” enums that represent the range of versions that an API is deprecated for:

```swift
extension Availability
{
    @frozen public
    enum EternalRange
    {
        case unconditionally
    }
}

extension Availability
{
    @frozen public
    enum AnyRange:Equatable, Hashable, Sendable
    {
        case unconditionally
        case since(SemanticVersionMask?)
    }
}

extension Availability
{
    @frozen public
    enum VersionRange:Equatable, Hashable, Sendable
    {
        case since(SemanticVersionMask?)
    }
}

```

this is because only some deprecation ranges make sense for various availability domains:

```swift
extension Availability
{
    @frozen public
    enum AgnosticDomain:String, CaseIterable, Hashable, Equatable, Sendable
    {
        case swift = "Swift"
        case swiftPM = "SwiftPM"
    }
}
extension Availability.AgnosticDomain:AvailabilityDomain
{
    public
    typealias Deprecation = Availability.VersionRange
    public
    typealias Unavailability = Never
}

```

```swift
extension Availability
{
    @frozen public
    enum PlatformDomain:String, CaseIterable, Hashable, Sendable
    {
        case iOS
        case macOS
        ...
    }
}
extension Availability.PlatformDomain:AvailabilityDomain
{
    public
    typealias Deprecation = Availability.AnyRange
    public
    typealias Unavailability = Availability.EternalRange
}

```

and so forth. i feel like all these `{Eternal, Any, Version}Range` types are just a workaround for a lack of anonymous union types.

---

<div class="post-metadata">

**Author:** ![sspringer](https://avatars.discourse-cdn.com/v4/letter/s/e9c0ed/32.png) [@sspringer](https://forums.swift.org/u/sspringer)\
**Post date:** [May 26, 2023, 5:26am UTC](https://forums.swift.org/t/multiple-types/65023/52 "2023-05-26T05:26:51Z")

</div>

> [@bbrk24](#):
>
> Is there a reason you can’t have a custom type that’s `ExpressibleByStringLiteral`?

This would probably solve the issue for String, but this can only be part of a good solution. But thank you for the hint.

> [@mayoff](#):
>
> Another possible solution in your case is to add a `buildExpression` method to your `resultBuilder` for each acceptable type.

Thank you for the hint, I will evaluate this, maybe this is the solution I need. [**UPDATE:** This cannot cope with the recursive nature of some of the things I would like to use via my result builder, but may help with some edge cases.]

…So maybe I get this resolved, but I have the feeling that something “more easy”, “more straightforward” is missing here and that some kind of union types (as an enhancement to enums?) is missing here for _a more natural way to cope with such cases_ (although I have to confess I didn't think it through in any systematic way).

The crucial point here is that the idea for my problem (and I suppose for many similar problems) is “those are the types I want to let people put in here” (without the syntactical “ornaments” needed for enums), and I would like to express this in a clear and easy way, but what I need is knowledge about the special structure (result builders) used which is not really a clear expression of intent.

---

<div class="post-metadata">

**Author:** ![miku1958](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/miku1958/32/11936_2.png) [@miku1958](https://forums.swift.org/u/miku1958)\
**Post date:** [December 25, 2023, 2:52pm UTC](https://forums.swift.org/t/multiple-types/65023/53 "2023-12-25T14:52:02Z")

</div>

I've recently worked on a ts project, and I really like ts unions!

I think we can extend the current Type Parameter Packs to implement Type Union, we can actually write code that almost works now, but it's not elegant enough:

```swift
struct Union<each T: Equatable>: ExpressibleByValue {
	// ExpressibleByValue is something we are missing today

	let value: (repeat (each T)?)
	init(value: repeat (each T)? = nil) { // = nil is missing today
		self.value = (repeat each value)
	}

	static func ~=(pattern: (repeat (each T)?), value: Self) -> Bool {
		for (l, r) in repeat (each pattern, each value.value) { // It's not possible today.
			guard l == r else { return false }
		}
		return true
	}
}

```

\* Note that adding default values for optional Type Parameter Packs is not a worthwhile exercise since there is a String | String case, but for Union, String | String is meaningless so it can be done.

And the usage is similar to:

```swift
let union: String | Int = 1
// `String | Int` is the syntactic sugar for union
// `= 1` is provided by ExpressibleByValue, equivalent to (nil, 1)

switch union {
case let value as String:
	print(value)
case let value as Int:
	print(value)
}

enum NetworkError {
	case deviceNotFound
	case wifiNotConnect
}

enum ParserError {
	case rootIsArray
	case typeIsUndefined
}

let error: NetworkError | ParserError = .typeIsUndefined

switch error {
case .deviceNotFound:
	print("deviceNotFound")
case .wifiNotConnect:
	print("wifiNotConnect")
case .rootIsArray:
	print("rootIsArray")
case .typeIsUndefined:
	print("typeIsUndefined")
}

```

If I remove the ExpressibleByValue and the syntactic sugar, the above code works.

```swift

struct Union<each T: Equatable> {
	let value: (repeat (each T)?)
	init(value: repeat (each T)?) {
		self.value = (repeat each value)
	}
}

let union: Union<String, Int> = .init(value: nil, 1)

switch union.value {
case let (.some(value), nil):
	print(value)
case let (nil, .some(value)):
	print(value)
default:
	break
}

enum NetworkError {
	case deviceNotFound
	case wifiNotConnect
}

enum ParserError {
	case rootIsArray
	case typeIsUndefined
}

let error: Union<NetworkError, ParserError> = .init(value: nil, .typeIsUndefined)

switch error.value {
case let (.some(value), nil):
	switch value {
	case .deviceNotFound:
		print("deviceNotFound")
	case .wifiNotConnect:
		print("wifiNotConnect")
	}
case let (nil, .some(value)):
	switch value {
	case .rootIsArray:
		print("rootIsArray")
	case .typeIsUndefined:
		print("typeIsUndefined")
	}
default:
	break
}

```

Perhaps a better approach would be for the compiler to rewrite union as enum or tuple. If it's tuple, it's perfectly fine with the current compiler.

---

<div class="post-metadata">

**Author:** ![Dmitriy\_Ignatyev](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dmitriy_ignatyev/32/11340_2.png) [@Dmitriy\_Ignatyev](https://forums.swift.org/u/Dmitriy_Ignatyev)\
**Post date:** [January 4, 2024, 11:13pm UTC](https://forums.swift.org/t/multiple-types/65023/54 "2024-01-04T23:13:36Z")

</div>

> [@AlexanderM](#):
>
> Really, why might something return a `String | Int`

Sometimes it is required by business logic. I can provide example with delivery date: imagine we have a list of products. Each of them have two properties: `deliveryDate: Date` and `deliveryText: String?`.  
Both `Date`& `String` are about delivery day / time in this case. Which one is chosen depends on several rules. Different formats, styles and colors.

Another one example is when the same kind of objects are get from server with different ID kinds: UUID and UInt64 for example.

But in my own opinion type union is the worst choice here. We have several alternatives:

- Either type
- convert Date string and and pass it as a tuple of String and some sort of flag
- use generic function like `func foo(bar: some CustomStringConvertible)`

Personally I believe that using union types people in general will do "incorrect things" instead of making better api design.

Seems that feature is requested by people with background in other languages, but not deeply familiar with Swift.

---

<div class="post-metadata">

**Author:** ![Dmitriy\_Ignatyev](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dmitriy_ignatyev/32/11340_2.png) [@Dmitriy\_Ignatyev](https://forums.swift.org/u/Dmitriy_Ignatyev)\
**Post date:** [January 4, 2024, 11:17pm UTC](https://forums.swift.org/t/multiple-types/65023/55 "2024-01-04T23:17:01Z")

</div>

Can you please provide some real world tasks where type unions are needed and the solution can not be expressed with current syntax or language constructs.

---

<div class="post-metadata">

**Author:** ![sspringer](https://avatars.discourse-cdn.com/v4/letter/s/e9c0ed/32.png) [@sspringer](https://forums.swift.org/u/sspringer)\
**Post date:** [January 5, 2024, 12:57am UTC](https://forums.swift.org/t/multiple-types/65023/56 "2024-01-05T00:57:33Z")

</div>

> [@Dmitriy\_Ignatyev](#):
>
> Can you please provide some real world tasks where type unions are needed …

[Typed throws](https://forums.swift.org/t/accepted-se-0413-typed-throws/69099).

> [@Dmitriy\_Ignatyev](#):
>
> … and the solution can not be expressed with current syntax or language constructs.

This is the wrong question, the question should be if there is a “simple enough” or “good enough” solution.

---

<div class="post-metadata">

**Author:** ![AlexanderM](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/alexanderm/32/9781_2.png) [@AlexanderM](https://forums.swift.org/u/AlexanderM)\
**Post date:** [January 5, 2024, 1:01am UTC](https://forums.swift.org/t/multiple-types/65023/57 "2024-01-05T01:01:35Z")

</div>

> Each of them have two properties: `deliveryDate: Date` and `deliveryText: String?`.

Why would the delivery date be a string?

> [@Dmitriy\_Ignatyev](#):
>
> Seems that feature is requested by people with background in other languages, but not deeply familiar with Swift.

100%.

---

<div class="post-metadata">

**Author:** ![miku1958](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/miku1958/32/11936_2.png) [@miku1958](https://forums.swift.org/u/miku1958)\
**Post date:** [January 5, 2024, 2:57am UTC](https://forums.swift.org/t/multiple-types/65023/58 "2024-01-05T02:57:28Z")

</div>

You're right, in fact most of the scenarios where Union can be used can be implemented manually in Swift, essentially Union can be understood as a compiler's way of simplifying the code for us, first of all, as I said earlier, the compiler can rewrite Union to deal with different types of Enums/Tuples, so in turn Union can be implemented as a much simpler alternative to dealing.  
Other examples are:

1. Typed throws need to throw more than one type of error, I can use a throw from the Error inheritance of the Protocol, and then manually check which type of error at runtime, with Union can be simplified to

```swift
throw(Error1|Error2)

```

and

```swift
catch error as Error1 { }
catch error as Error2 { }

```

1. If a method accepts String or Int or Double or Data or any other type that can be converted to String according to a specific rule, I can create a new protocol StringConvertible, and implement StringConvertible for String, Int, Double, Data, and then use StringConvertible, and then return the corresponding string, and then use StringConvertible as a parameter, or I can create four methods with the same name to handle each of the four different types, or use Enum.  
With Union, I can simplify it to (String|Int|Double|Data) as a parameter, and then switch the union in the method to get the target string(like the Enum approach), without creating a new type.
2. If several types have common methods (such as the `text ` of TextView, Label and TextField), and I need to deal with these types at the same time, and only use these common methods, the original approach is usually to add a Protocol and add the common methods to the Protocol and then deal with the Protocol can be, with Union is `(view: TextView|Label|TextField)`, and then directly use `view.text`.

---

<div class="post-metadata">

**Author:** ![Dmitriy\_Ignatyev](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dmitriy_ignatyev/32/11340_2.png) [@Dmitriy\_Ignatyev](https://forums.swift.org/u/Dmitriy_Ignatyev)\
**Post date:** [January 5, 2024, 7:58pm UTC](https://forums.swift.org/t/multiple-types/65023/59 "2024-01-05T19:58:46Z")

</div>

> [@AlexanderM](#):
>
> > Each of them have two properties: `deliveryDate: Date` and `deliveryText: String?`.
> 
> Why would the delivery date be a string?

When it is of `Date` type it is formatted locally on device as "today", "tomorrow", "January 16th"...  
When it is of type `String` no formatting is needed as text is prepared on server, something like "in 1 hour', "super fast", "soon"...

---

<div class="post-metadata">

**Author:** ![Pippin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/pippin/32/24826_2.png) [@Pippin](https://forums.swift.org/u/Pippin)\
**Post date:** [January 5, 2024, 8:05pm UTC](https://forums.swift.org/t/multiple-types/65023/60 "2024-01-05T20:05:54Z")

</div>

> [@Dmitriy\_Ignatyev](#):
>
> When it is of `Date` type it is formatted locally on device as "today", "tomorrow", "January 16th"...

A Swift `Date` represents a point in time, irrespective of locale or anything us silly humans have come up with like "calendars" or "formatting".

* * *

If one wants to have types that "can be in X or Y form, depending on the context" they're only asking for trouble.

[Previous page](https://forums.swift.org/t/multiple-types/65023.md?page=2)

[Next page](https://forums.swift.org/t/multiple-types/65023.md?page=4)
