UniquelyTypedID Swift 宏

当传递字符串或整数作为 ID 时,编译器不会提示你是否将 person ID 传递到了 blog post ID 的位置。现在有了 UniquelyTypedID,编译器将阻止你传递不同模型的 ID。

并且凭借 ExpressibleByStringLiteralExpressibleByIntegerLiteral 的强大功能,只需要修改极少量的代码。

我已经在自己的项目中使用了这种方法来保证记录 ID 的类型安全,通常是通过手动复制粘贴实现的。现在有了 Swift 5.9 中的 Swift 宏,这将变得容易得多。

安装

在 Package.swift 中,将此包添加到你的依赖项中。

.package(url: "https://github.com/FullQueueDeveloper/UniquelyTypedID.git", from: "1.0.0"),

并将 "UniquelyTypedID" 添加到你的 target 依赖项列表中。

当 Xcode 提示时,信任该宏。

用法

如果你有一个整数 ID

struct BlogPost {
  let id: Int
  let text: String
}

那么你可以使用这个宏来代替。

struct BlogPost {
  @UniquelyTypedId(Int.self) let id: ID
  let text: String
}

其中 ID 是你希望的 ID 类型名称。我倾向于简单地使用 ID,这样我可以轻松地通过 BlogPost.ID 引用该类型。

特性 & 支持的类型

目前,支持 IntStringUUID。如果没有指定类型,该宏默认使用 UUID

所有生成的 ID 都是 Hashable 的。

所有生成的 ID 都是 Codable 的,并且它们编码为单值容器,以便在从普通整数或字符串 ID 升级时获得最大的兼容性。

字符串

UniquelyTypedId 生成的字符串 ID 类型可以通过字符串字面量表达。这使得硬编码数据输入更加容易。

struct Vegetable {
  @UniquelyTypedId(String.self) let scientificName: ScientificName
  let name: String
}

let chili = Vegetable(scientificName: "Capsicum annuum", name: "Chili")

如果我们把这个 chili 编码成 JSON,我们会看到

{
  "name" : "Chili",
  "scientificName" : "Capsicum annuum"
}

整数

UniquelyTypedId 生成的整数 ID 类型可以通过字符串字面量表达。这使得硬编码数据输入更加容易。

例如

struct Aubergine: Codable {
  @UniquelyTypedID(Int.self) let id: ID
  let name: String
}

let aubergineID: Aubergine.ID = 3
let aubergine = Aubergine(id: 9, name: "Fairy Tale")

Swift 宏?

在 WWDC '23 上推出,需要 Swift 5.9

许可证

BSD-3-Clause