我有一个函数,该函数采用具有相同类型的子数组的对象。现在,我想将孩子列表转换为由孩子ID索引的对象。
我想在Typescript中对此建模,并执行以下操作:
export const convertHierarchyToDiffFriendly = <T extends {id: string, children?: T[]}, U extends T & {children: {[id: string]: U}}>(x: T): U => (<U>{
...x,
children: x.children ?
<U["children"]>x.children.reduce((z, y) => ({
...z,
[y.id]: convertHierarchyToDiffFriendly(y)}),
<{[id: string]: U}>{}) : {}
})
这可行,但是:
const convertedRhs = convertHierarchyToDiffFriendly(<IVendorStatusInput>rhs)
const c = convertedRhs.children["10"] // c's type is {}, not T & {children: {[id]: U}}
很明显,U不能正确导出,但是怎么可能呢?
答案 0 :(得分:1)
我不认为您希望U
是通用的。相反,您希望它是T
类型的函数,并使用mapped和conditional类型,如下所示:
type ConvertToDiffFriendly<T extends { id: string, children?: T[] }> = {
[K in keyof T]: "children" extends K ? { [id: string]: ConvertToDiffFriendly<T> } : T[K]
};
因此,ConvertToDiffFriendly<T>
与T
相同,只是其children
属性(如果有)改变了类型。现在,您可以像下面这样键入函数:
export const convertHierarchyToDiffFriendly = <T extends { id: string, children?: T[] }>(
x: T
): ConvertToDiffFriendly<T> => ({
...x,
children: x.children ?
x.children.reduce((z, y) => ({
...z,
[y.id]: convertHierarchyToDiffFriendly(y)
}),
<{ [id: string]: ConvertToDiffFriendly<T> }>{}) : {}
} as ConvertToDiffFriendly<T>)
我没有检查实现的正确性,但是类型应该合理。
最后,让我们对其进行测试:
interface IVendorStatusThingy {
id: string,
children: IVendorStatusThingy[],
limbs: number,
withCheese: boolean
}
declare const rhs: IVendorStatusThingy;
const convertedRhs = convertHierarchyToDiffFriendly(rhs)
const c = convertedRhs.children["10"]
// c's type is ConvertToDiffFriendly<IVendorStatusThingy>
对我很好。希望能有所帮助;祝你好运!