我需要使用一个或某些测试函数来测试多个HTMLInputElement
的每个值,并自动为每个复选框生成嵌套的复选框列表,条件表示为{{1} }:
Conditions
例如,如果我有:
type TestFunction = (value: string) => boolean
type TestFunctionObject = { [description: string]: Conditions }
type Conditions = TestFunction | TestFunctionObject
我得到一个标记为“由字母数字组成”的复选框。如果:
const conds1: Conditions = {
"Consists of alphanumerics": /^[a-zA-Z0-9]$/.test
}
我不想要一个复选框,而只是对其进行验证。
自动生成已完成,没有任何问题。然后,我写了一个表示每个const conds2: Conditions = /^[a-zA-Z0-9]$/.test
的有效性的类型:
TestFunction
现在我在type Validity<C extends Conditions> = C extends TestFunction
? boolean
: { [K in keyof C]: Validity<C[K]> }
上从TS收到了一个错误; playground here。它说C[K]
。类型调节似乎不会将Type 'Conditions[K]' is not assignable to type 'TestFunctionObject'
缩小到Conditions
。
我如何使它工作?
答案 0 :(得分:2)
我不认为编译器在条件类型的else子句中(在:
之后)不会像通过控制流分析对值进行处理那样进行大量缩小。因此,虽然很明显在条件类型C extends TestFunction
中,else子句中的C
应该扩展TestFunctionObject
,但编译器没有意识到。
但是编译器确实在then子句中(在?
和:
之间)变窄,因此最简单的解决方法是添加另一个条件类型:>
type Validity<C extends Conditions> = C extends TestFunction ? boolean
: C extends TestFunctionObject ? { [K in keyof C]: Validity<C[K]> } : never
请注意,最后一个条件类型具有never
作为else子句。这是带有条件类型的常见习语。有时,您知道无法达到else子句;并且在没有invalid type的情况下,never
类型是一个很好的选择。
或者,由于开始时对then子句的处理不多,因此请翻转原始支票的子句:
type Validity<C extends Conditions> = C extends TestFunctionObject ?
{ [K in keyof C]: Validity<C[K]> } : boolean
应该都可以。希望能有所帮助;祝你好运!