我正在寻找一个类型Validate
,它将强制执行类似以下内容
// validate
const myObj: Validate<'value', boolean> = {
value: true,
otherValue: 'its value',
nestedProp: {
value: false
}
}
// does not validate
const myObj: Validate<'value', boolean> = {
value: true,
otherValue: 'its value',
nestedProp: {
value: 0 // not of type boolean
}
}
其中泛型的第一个参数是嵌套属性的名称,第二个参数是要强制的类型。
这可能吗?
编辑:其思想是在使用联合类型而不是该示例中的boolean
时从IDE中获得自动完成。
type ColorType = 'red' | 'green'
type ColoredObject<T> = {
[P in keyof T]: T[P] extends object ? ColoredObject<T[P]> : T[P];
} & { color: ColorType };
const myObject: ColoredObject<{ prop1: { prop2: { color: string } } }> = {
color: 'red',
prop1: {
color: 'red',
prop2: {
color: 0 // this would fail
}
}
};
在上面的例子中,它按照我想要的方式工作,但是它使color属性成为必需的。有没有一种方法可以使它成为可选的而不违反要求?同样,这要求我将对象接口作为泛型传递,我不希望这样,因为我可能不知道它。
编辑2:或者这个,但是除了颜色,它不允许任何其他的 prop
type ColoredObject<T, P, V> = {
[P in keyof T]: T[P] extends object ? ColoredObject<T[P], P, V> : T[P] extends 'color' ? V : never
}
type ColorType = 'red' | 'green'
const test: ColoredObject<any, 'color', ColorType> = {
color: 'green',
otherProps: 'lala', // <---- fails here
props: {
color: 'green'
}
}
2条答案
按热度按时间qxgroojn1#
给定一个键类型
K
和一个值类型V
,是否存在一个特定的类型Validate<K, V>
来执行您希望执行的规则并不明显,通常当很难或不可能编写对应于某个规则的特定类型时,编写 * 检查 * 候选类型是否遵守该规则的generic类型变得简单得多。因此,您使用
T extends Validate<T, K, V>
而不是Validate<K, V>
作为自引用类型 constraint。为了避免手动指定T
类型,您可以编写一个通用帮助器函数来为您 * infert * 它。因此,从概念上讲,该方法是:而不是
const x: Validate<K, V> = ...
,您可以编写以下形式的函数然后写
const x = validateKV(...);
。当然,这并不总是那么容易;T extends Validate<T, K, V>
通常被认为是非法的循环约束,要解决这个问题,您需要使用conditional types,例如你可能不想为每一个可能的
K
和V
写一个新的helper函数,所以它也应该是泛型的,不幸的是,你不能得到“部分推理”,在这里你指定K
和V
,但是编译器推理V
(参见microsoft/TypeScript#26242了解特性请求),因此您需要解决这个问题(参见Typescript: infer type of generic after optional first generic了解更多信息),最简单的方法是 currying,如下所示:一旦我们定义了
Validate<T, K, V>
,这就是我们要用到的。这就是:
其思想是,如果
T
是一个基元类型,那么Validate<T, K, V>
就是T
,因此Validate<T, K, V>
将自动接受任何基元类型,另一方面,如果它是一个对象类型,则Validate<T, K, V>
是mapped type,其中检查每个属性键P
。如果属性键P
碰巧与特殊键K
相同,那么我们需要确保它具有值类型V
,否则,我们只需要向下递归并确保属性类型T[P]
对于相同的K
和V
可赋值给Validate<T[P], K, V>
。让我们来测试一下,对于
"value"
的特定K
和boolean
的特定V
,如问题代码中所提到的。首先,我们需要使用curried outer函数:现在我们可以试试。
该类型根据需要进行检查。在每个级别上,名为
value
的属性都具有boolean
类型的值。请将其与以下内容进行对比:这是一个编译器错误,特别是错误的
value
属性,它告诉你3
是一个number
,而预期的是boolean
。如果你修复了这个错误,那么这个错误就会消失。所以,看起来不错。考虑到语言的限制和我对用例的理解,这是我所能想象的最接近你想要的类型。
Playground代码链接
2lpgd9682#
这个怎么样?
感谢Titian的评论