这道题是here题的延伸.
我有一个目标:
type exampleType = {
propertyOne: string
propertyTwo: number,
propertyThree: {
propertyFour: string,
propertyFive: Date,
propertySix: boolean,
}
}
我正在寻找一种类型,可以将像字符串这样的点符号验证为路径string
或Date
.在上面的示例中,这意味着该类型将编译为:
propertyOne | propertyThree.propertyFour | propertyThree.PropertyFive
使用前面提出的问题,可以实现以下目标:
type PathsToStringProps<T> = T extends string ? [] : {
[K in Extract<keyof T, string>]: [K, ...PathsToStringProps<T[K]>]
}[Extract<keyof T, string>];
type Join<T extends string[], D extends string> =
T extends [] ? never :
T extends [infer F] ? F :
T extends [infer F, ...infer R] ?
F extends string ?
`${F}${D}${Join<Extract<R, string[]>, D>}` : never : string;
type Path = Join<PathsToStringProps<exampleType>, ".">
我正在try 使上面的解决方案成为泛型,这样我就可以为Path
提供两个泛型参数:T
,在这里代表exampleType
,V
,在我上面的例子中,它是string|Date
.
当我试着让exampleType
个通用的时候:
type Path<T> = Join<PathsToStringProps<T>, ".">
我收到了这个错误:Excessive stack depth comparing types 'PathsToStringProps<T>' and 'string[]'.ts(2321)
我可以通过指定T必须表示键值对象来解决这个问题:
type Path<T extends {[key: string]: any}> = Join<PathsToStringProps<T>, ".">
接下来,将值类型限制为路径指向:
type PathsToStringProps<T, V> = T extends (V) ? [] : {
[K in Extract<keyof T, string>]: [K, ...PathsToStringProps<T[K], V>]
}[Extract<keyof T, string>];
type Join<T extends string[], D extends string> =
T extends [] ? never :
T extends [infer F] ? F :
T extends [infer F, ...infer R] ?
F extends string ?
`${F}${D}${Join<Extract<R, string[]>, D>}` : never : string;
type Path<T extends {[key: string]: any}, V> = Join<PathsToStringProps<T, V>, ".">
但我得到了一个错误:
如果我将泛型参数V从Path
中删除,但将其保留在PathsToStringProps
中,则它将消失:
type Path<T extends {[key: string]: any}> = Join<PathsToStringProps<T, string|Date>, ".">
Here's a TypeScript Playground of my final attempt at getting this to work.个