这不起作用,但是我想做这样的事情:
type ProxyNestedKeys<O> = {
[P in Extract<keyof O, string> Q in Extract<keyof O[P], string>]: boolean
}
以便ProxyNestedKeys可以通过O的嵌套属性建立索引。
例如,如果我正在构建执行以下操作的验证库:
const schema = {
foo: {
minVal: 2,
maxVal: 5
}
}
const state = { foo: 6 }
const result = validate(schema, state)
// result
{
foo: {
$isValid: false
$validations: {
minVal: true
maxVal: false
}
}
}
所以结果就是我要输入的内容,到目前为止,我已经知道了:
// S is the state and V is the schema
type Validation<S, V> = {
[K in Extract<keyof S, keyof V>]: Validation<S[K], V[K]>
} & {
$isValid: boolean
$validations: what goes here?
}
我不需要递归地将所有道具加深一个层次。
答案 0 :(得分:1)
更新建议的用法
类似这样的东西
const schema = {
foo: {
minVal: 2,
maxVal: 5
}
}
type ValidationResult<S> = {
[K in keyof S]: {[VK in keyof S[K]]: boolean} & {$isValid: boolean}
}
const state = { foo: 6 }
declare function validate<S,V>(schema: S, value: V): ValidationResult<S>;
const result = validate(schema, state);
旧人
我想写这样的话
type FlattenByKeys<K extends keyof T, T> = K extends any ?
(T[K] extends object ? FlattenByKeys<keyof T[K], T[K]> : withKey<K, T[K]> ):
never;
但是TypeScript对于递归类型有一些限制。所以有workaround
type WithKey<K extends string | number | symbol, T> = {
[k in K]: T
}
type FlattenByKeys<K extends keyof T, T> = K extends any ?
(T[K] extends object ? {__r: FlattenByKeys<keyof T[K], T[K]>} : WithKey<K, T[K]> ):
never;
type FR<T> = T extends {__r: infer U} ? U : T;
type FR10<T> = FR<FR<FR<FR<FR<FR<FR<FR<FR<FR<FR<T>>>>>>>>>>>;
type UnionToIntersection<U> =
(U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never
type Pretty<T> = {
[K in keyof T] : T[K]
}
const v = {
a: 1,
b: 2,
c: {
x: 1,
y: 2,
d: {
l: '5',
m: '6'
}
}
};
type V = typeof v;
/*
type Test = {
a: number;
b: number;
x: number;
y: number;
l: string;
m: string;
}
*/
type Test = Pretty<UnionToIntersection<FR10<FlattenByKeys<keyof V, V>>>>;