A Swift macro package that generates case labels for enumerations with associated values. Case labels allow comparing enum cases by their label, ignoring associated values.
Apply the @CaseLabeled macro to an enumeration to generate a nested CaseLabel enum and a caseLabel property:
@CaseLabeled
enum MyEnum: Equatable {
case intValue(Int)
case stringValue(string: String)
}The generated CaseLabel enum mirrors the cases of the original enum without associated values and conforms to Hashable, CaseIterable, and Sendable. The caseLabel property returns the matching CaseLabel for each case.
Case labels can identify values with the same case, even if their associated values differ.
The ~~ operator and the hasSameLabel(as:) method compare two values by their case label:
let value1: MyEnum = .intValue(1)
let value2: MyEnum = .intValue(2)
value1 == value2 // false - different associated values
value1 ~~ value2 // true - same case label
value1.hasSameLabel(as: value2) // true - same case labelEnum values can also be compared directly with CaseLabel values using ~=:
value1 ~= .intValue // true
value1 ~= .stringValue // falseCase labels work well with generic constraints on CaseLabeled:
@CaseLabeled
enum MyEnum: Hashable {
case intValue(Int)
case stringValue(string: String)
}
extension Set where Element: CaseLabeled {
func removing(_ labeled: Element.CaseLabel) -> Self {
filter { $0.caseLabel != labeled }
}
}
let values: Set<MyEnum> = [
.stringValue(string: "Text1"),
.intValue(1),
.intValue(2),
.stringValue(string: "Text2"),
]
let filtered = values.removing(.intValue)
// Only stringValue cases remainThe @CaseLabeled macro cannot be used on private enums nested inside another type. The macro generates a protocol conformance extension at file scope, where a truly private nested type is not visible. The following code will not compile:
struct Container {
@CaseLabeled
private enum MyEnum {
case intValue(Int)
case stringValue(string: String)
}
}The same applies to enums in private extensions:
private extension Namespace {
@CaseLabeled
enum MyEnum {
case intValue(Int)
case stringValue(string: String)
}
}As a workaround, you can declare the CaseLabeled conformance directly on the enum. The macro detects the existing conformance and skips generating the extension:
struct Container {
@CaseLabeled
private enum MyEnum: CaseLabeled {
case intValue(Int)
case stringValue(string: String)
}
}- Swift 6.0+
- macOS 13+, iOS 16+, tvOS 16+, watchOS 9+, visionOS 1+
Add the package dependency to your Package.swift:
dependencies: [
.package(url: "https://github.com/wiedem/enum-case-labeling", .upToNextMajor(from: "2.0.0")),
]Then add "EnumCaseLabeling" to your target's dependencies:
.target(
name: "YourTarget",
dependencies: [
.product(name: "EnumCaseLabeling", package: "enum-case-labeling"),
]
)This project is licensed under the MIT License. See the LICENSE file for details.