DeepRequired<T> with Shift<T> 不可分配
DeepRequired<T> with Shift<T> not assignable
我正在尝试编写一个实用程序,可以根据需要设置对象的深度键。
什么有效
到目前为止,我想出了一种方法来获取对象的所有可能 Leaves
,我想将其用于路径验证。它将所有键路径收集到数组中,但在可选键处停止以解决无限深度问题。
然后,我还制作了DeepRequired
,它根据传递的叶子将属性设置为必需的:
type Person = {
name: string;
father?: Person;
mother?: Person;
siblings?: Person[];
contact: {
email: string;
};
created_at: Date;
};
type PersonLeaves = Leaves<Person>;
// type PersonLeaves = ["name"] | ["father"] | ["mother"] | ["siblings"] | ["contact", "email"];
type PersonWithParents = DeepRequired<Person, ["father" | "mother"]>;
// type PersonWithParents = {
// name: string;
// father: Person; // Note how this is now required
// mother: Person; // Note how this is now required
// siblings?: Person[];
// contact: {
// email: string;
// };
// created_at: Date;
// }
type PersonWithFatherSiblings = DeepRequired<DeepRequired<Person, ["father"]>, ["father", "siblings"]>;
// type PersonWithFatherSiblings = {
// name: string;
// father: PersonWithSiblings; // Father is required, then father's siblings is required.
// mother?: Person;
// siblings?: Person[];
// contact: {
// email: string;
// };
// created_at: Date;
// }
问题
这些实用程序似乎都按预期工作,但我在 DeepRequired
定义中的 Shift
确实遇到了错误,而且我在 vscode 中没有得到任何路径建议使用 DeepRequired
.
编写类型时
Type 'Shift<P>' does not satisfy the constraint 'Leaves<T[K]>'.
Type 'unknown[] | []' is not assignable to type 'Leaves<T[K]>'.
Type 'unknown[]' is not assignable to type 'Leaves<T[K]>'.
我想弄清楚为什么会这样。有人可以帮助改进吗?
TL;DR
请参阅 playground 以查看带有错误的工作示例
谢谢!
请告诉我它是否适合你:
type Concat<T extends any, A extends any[]> = [T, ...A];
type Shift<T extends any[]> = T extends [infer _, ...infer A] ? A : [];
type OptionalKeys<T extends object> = {
[K in keyof T]-?: T extends Record<K, T[K]> ? never : K;
}[keyof T];
type Leaves<T> = T extends (infer U)[]
? Leaves<U>
: T extends object
? {
[K in keyof T]-?: K extends OptionalKeys<T>
? [K]
: Concat<K, Leaves<T[K]>>;
}[keyof T]
: [];
type DeepRequired<T, P extends Leaves<T>> = T extends object
? Omit<T, Extract<keyof T, P[0]>> &
Required<
{
// Shift did not satisfied constraint, so I added condition
[K in Extract<keyof T, P[0]>]: Shift<P> extends Leaves<T[K]> ? DeepRequired<T[K], Shift<P>> : never
}
>
: T;
type Person = {
name: string;
father?: Person;
mother?: Person;
siblings?: Person[];
contact: {
email: string;
};
created_at: Date;
};
type PersonLeaves = Leaves<Person>;
type PersonWithParents = DeepRequired<Person, ["father" | "mother"]>;
type PersonWithFatherSiblings = DeepRequired<DeepRequired<Person, ["father"]>, ["father", "siblings"]>;
我正在尝试编写一个实用程序,可以根据需要设置对象的深度键。
什么有效
到目前为止,我想出了一种方法来获取对象的所有可能 Leaves
,我想将其用于路径验证。它将所有键路径收集到数组中,但在可选键处停止以解决无限深度问题。
然后,我还制作了DeepRequired
,它根据传递的叶子将属性设置为必需的:
type Person = {
name: string;
father?: Person;
mother?: Person;
siblings?: Person[];
contact: {
email: string;
};
created_at: Date;
};
type PersonLeaves = Leaves<Person>;
// type PersonLeaves = ["name"] | ["father"] | ["mother"] | ["siblings"] | ["contact", "email"];
type PersonWithParents = DeepRequired<Person, ["father" | "mother"]>;
// type PersonWithParents = {
// name: string;
// father: Person; // Note how this is now required
// mother: Person; // Note how this is now required
// siblings?: Person[];
// contact: {
// email: string;
// };
// created_at: Date;
// }
type PersonWithFatherSiblings = DeepRequired<DeepRequired<Person, ["father"]>, ["father", "siblings"]>;
// type PersonWithFatherSiblings = {
// name: string;
// father: PersonWithSiblings; // Father is required, then father's siblings is required.
// mother?: Person;
// siblings?: Person[];
// contact: {
// email: string;
// };
// created_at: Date;
// }
问题
这些实用程序似乎都按预期工作,但我在 DeepRequired
定义中的 Shift
确实遇到了错误,而且我在 vscode 中没有得到任何路径建议使用 DeepRequired
.
Type 'Shift<P>' does not satisfy the constraint 'Leaves<T[K]>'.
Type 'unknown[] | []' is not assignable to type 'Leaves<T[K]>'.
Type 'unknown[]' is not assignable to type 'Leaves<T[K]>'.
我想弄清楚为什么会这样。有人可以帮助改进吗?
TL;DR
请参阅 playground 以查看带有错误的工作示例
谢谢!
请告诉我它是否适合你:
type Concat<T extends any, A extends any[]> = [T, ...A];
type Shift<T extends any[]> = T extends [infer _, ...infer A] ? A : [];
type OptionalKeys<T extends object> = {
[K in keyof T]-?: T extends Record<K, T[K]> ? never : K;
}[keyof T];
type Leaves<T> = T extends (infer U)[]
? Leaves<U>
: T extends object
? {
[K in keyof T]-?: K extends OptionalKeys<T>
? [K]
: Concat<K, Leaves<T[K]>>;
}[keyof T]
: [];
type DeepRequired<T, P extends Leaves<T>> = T extends object
? Omit<T, Extract<keyof T, P[0]>> &
Required<
{
// Shift did not satisfied constraint, so I added condition
[K in Extract<keyof T, P[0]>]: Shift<P> extends Leaves<T[K]> ? DeepRequired<T[K], Shift<P>> : never
}
>
: T;
type Person = {
name: string;
father?: Person;
mother?: Person;
siblings?: Person[];
contact: {
email: string;
};
created_at: Date;
};
type PersonLeaves = Leaves<Person>;
type PersonWithParents = DeepRequired<Person, ["father" | "mother"]>;
type PersonWithFatherSiblings = DeepRequired<DeepRequired<Person, ["father"]>, ["father", "siblings"]>;