ValidatedExtension
ValidatedExtension 是一个 μ 库,允许您通过提供工具来轻松生成具有内置保证的新类型,从而更好地利用 Swift 的类型系统。它是 Ben-G/Validated 的派生 jersonperpetua/Validated(添加了 ValidatedType
)的分支。ValidatedExtension 删除了 Validated
的不必要的第一个泛型参数,允许验证器通过抛出错误来失败,并添加了对 Swift 包管理器和 Swift 3.0 的支持。
Validated 允许您使用类型系统来验证值的属性,提供编译时间保证的新级别。
使用验证器,您可以定义新类型,这些类型向现有类型添加保证
// Create a new string type that can never be empty
typealias NonEmptyString = Validated<NonEmptyStringValidator>
示例
您可能有一个在您的代码中只有一个知道如何处理登录用户 User
值的函数。通常,您会在代码中实现此要求并添加文档说明,但没有简单的方法在类型签名中表达此不变性。
/// Please ever only call with a logged-in user!
func performTaskWithUser(user: User) {
precondition(
user.loggedIn,
"It is illegal to call this method with a logged out user!"
)
// ...
}
使用 Validated,您可以快速创建一个新类型,该类型在类型系统中描述了这个要求。这使得无法以未登录用户的身份调用该函数,并使方法签名表达您的约束(而不是依靠文档)
func performTaskWithUser(user: LoggedInUser) {
// ...
}
那么,如何创建这个新的 LoggedInUser
类型呢?
首先,您需要实现一个验证器
struct LoggedInValidator: Validator {
static func validate(value: User) throws -> Bool {
return value.loggedIn
}
}
一个 Validator
需要实现一个 validate
函数,该函数接收该验证器可以验证的类型(在这种情况下是 User
)。函数返回一个 Bool
。如果满足要求则返回 true
,如果不满足则返回 false
。
有了 Validator
后,我们可以这样创建我们的新类型
typealias LoggedInUser = Validated<LoggedInValidator>
请注意,不提供 typealias 不是必需的,但对于大多数情况,这是推荐的。
就这样!
LoggedInUser
现在有一个可能失败的初始化器,它接受一个 User
。如果传入的 User
满足登录要求,则您将拥有一个 LoggedInUser
,否则 nil
。此外,LoggedInUser
还提供了一个抛出初始化器,如果您更愿意将失败的验证作为错误而不是 nil
值来处理。
基础值(完整的 User
值)存储在 LoggedInUser
的 .value
属性中。
基础知识之外
Validated 提供了一些可能不明显的额外功能。
使用逻辑运算符组合验证器
Validated 提供了用于逻辑操作的 Validator
类型,允许您以不同的组合要求多个验证。例如,您可以使用 And
验证器要求满足两个条件才能初始化您的类型。
typealias AllCapsNonEmptyString =
Validated<And<NonEmptyStringValidator, AllCapsLatinStringValidator>>
此外还提供了 Or
和 Not
作为附加验证器。您可以查看规范获取更多示例。
泛型验证器
Validator
本身也可以是泛型的。如果您想为一类类型提供验证,这将很有用。例如,示例验证器 NonEmptyCollectionValidator
通过使用泛型要求可以应用于所有验证器类型。
struct NonEmptyCollectionValidator<T: CollectionType>: Validator {
static func validate(value: T) -> Bool {
if !value.isEmpty {
return true
} else {
return false
}
}
}
然而,当使用此验证器创建类型时,您将必须指定要验证的确切集合类型。
typealias NonEmptyListOfStrings = Validated<NonEmptyCollectionValidator<[String]>>
这个库支持依赖类型吗?
不是的。依赖类型将使我们能够仅基于值定义类型。此库仅允许我们基于值和验证器验证类型是否为指定的类型 <T>
。值本身不会改变类型信息。
真正依赖类型将产生以下结果
[1, 2, 3] // type = Array<count:3 type:Int>
[1, 2, 3, 4] // type = Array<count:4 type:Int>
使用 Validated 我们只能验证类型是否属于我们静态定义的某一类别
ListOf3([1,2,3]) // type = ListOf3<Array<Int>
ListOf3([1,2,3,4]) // type = nil
但是,这些静态提供的检查仍然可以为您的代码添加很多价值;请参阅上面的示例。
安装
Validated 通过通常的方式提供。
CocoaPods
您可以通过在 Podfile
中添加 Validated 来使用 CocoaPods 安装它
use_frameworks!
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
pod 'ValidatedExtension'
并运行 pod install
。
Carthage
您可以通过向 Cartfile 添加以下行来通过 Carthage 安装 ValidatedExtension
github "vknabel/ValidatedExtension"
联系方式
如果您有任何问题,您可以在 Twitter 上找到我 @vknabel。