ValidatedExtension 4.0.0

ValidatedExtension 4.0.0

测试已测试
语言语言 SwiftSwift
许可证 MIT
发布上次发布2016年9月
SPM支持 SPM

Valentin Knabel 维护。



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>>

此外还提供了 OrNot 作为附加验证器。您可以查看规范获取更多示例。

泛型验证器

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