字段模板



本文有许多模板,可以让我们给结构体字段添加复杂的约束和验证。

OneOf

OneOf 模板用于强制一组字段中的一个且只有一个,我们使用析取符和嵌入来创建。

oneOf.cue

#OneOf: {a: string} | {b: string}

#E: {
	name: string
	#OneOf
}

ex1: #E & {
	name: "a choice"
	a:    "bar"
}

ex2: #E & {
	name: "b choice"
	b:    "hello"
}

ex3: #E & {
	name: "error none chosen"
}

ex4: #E & {
	name: "error both chosen"
	a:    "a"
	b:    "b"
}

你也可以增加更多选项,如果你想让它们都失效也可以设置为空

oneOfMaybe.cue

#OneOf: {} | {a: string} | {b: string} | {c: int} | {d: bool}

然而,一个选项不能是其他选项的子集,如果只设置 a 下面的例子将会报错:

subsetFail.cue

#OneOf: {a: _} | {a: _, b: _}

CUE 不能区分这些选择。

AnyOf

AnyOf 模板用于选择一组字段中的至少一个。

AnyOf 需要用于验证的字段来检查可选的字段是否存在,这个模板用到了:

  • 一组可选字段,选择其中的一个或多个
  • 使用 this= 所以我们可以引用本地字段,你可以使用不同于 this 的字段
  • 使用 this 进行 list 推导,还用了 list.Contains() 来检查字段
  • 有个使用 true & list.MinItems 的定义,用于检查至少包含其中一个标签

anyOf.cue

import "list"

val: this={
	a?:        string
	b?:        string
	c?:        string
	#AnyOfABC: true & list.MinItems([ for label, _ in this if list.Contains(["a", "b", "c"], label) {label}], 1)

	d?:       string
	e?:       string
	#AnyOfDE: true & list.MinItems([ for label, _ in this if list.Contains(["d", "e"], label) {label}], 1)

	#AnyOfXYZ & {#CheckXYZ: true}

	a: "a"
	d: "d"
	z: "z"
}

#AnyOfXYZ: this={
	x?:        string
	y?:        string
	z?:        string
	#CheckXYZ: list.MinItems([ for label, _ in this if list.Contains(["x", "y", "z"], label) {label}], 1)
}

注意我们有两种不同的方式,基于自身判断的像 ABCDE,以及基于定义的 XYZ

如果你想的话,你也可以通过修改 list.MinItems 的第二个参数来修改所需的最少字段,也可以有重叠的集合。

注意,在必须字段和内置的提案提供更多原生的方法之前这算是一种解决方案

查看 cueology/futurology 获取提案的更多内容。

我们绝不会将你的邮箱分享给任何人。
2022 Hofstadter, Inc