我有一个验证函数,它接收要验证的值,还接收用于验证的配置对象。
const config = {type: 'foo'}
const value = {name: 'John', age: 22}
const isValid = (value: Value, config: Config) {
// some validation over here
}
这个值是两种类型的并集。我希望验证函数不仅能根据配置验证这个值,而且能将这个值的类型缩小到两种类型的并集之一。
type Value = Foo | Bar
根据配置,我知道应该将范围缩小到这两者中的哪一个。逻辑应该是这样的:
- 如果
config.type
为foo
,并且验证函数返回true,则其类型应为Foo
- 如果
config.type
为bar
,并且验证函数返回true,则其类型应为Bar
- 如果验证返回false,则类型应保持为
Value
示例:
type Config = {type: 'foo' | 'bar'}
type Foo = {name: string, age: number, something?: string}
type Bar = {name: string, age: number, somethingElse?: string}
type Value = Foo | Bar
const value: Value = {name: 'John', age: 22}
const config: Config = {type: 'foo'}
if (isValid(value, config)) {
// value should be narrowed down to Foo
}
const config2: Config = {type: 'bar'}
if (isValid(value, config2)) {
// value should be narrowed down to Bar
}
问题是,我应该如何修改isValid
函数,以便它根据配置和返回值缩小类型范围?
注意,配置在代码中是常量(尽管有多个不同的配置)。
2条答案
按热度按时间fxnxkyjh1#
对于所提出的问题,我倾向于在
K
中创建isValid()
generic,即config
参数的type
属性的literal type,并在适当的Map接口中使用类型 predicate 以looking upK
为单位缩小value
:那么我们可以这样使用它:
注意,我们不能只写
const config = {type: "foo"}
,否则编译器会推断它具有{type: string}
类型,该类型太宽而没有用,甚至不能赋值给Config
,有不同的方法可以让编译器推断出更合适的类型;你可以在初始化器上使用const
Assert,或者你可以做我上面所做的,并使用satisfies
操作符来提供你试图获得Config
兼容类型的上下文(而不是实际上一直扩展到Config
,这也不会有用)。无论如何,它看起来不错...当
isValid()
返回true
时,它在正确的位置将value
缩小为Foo
或Bar
。Playground代码链接
6rvt4ljy2#
你想实现这样的目标吗?