通用类型 return 不接受包含相同定义字段的对象
Generic type return does not accept object containing the same defined fields
我正在尝试编写一个函数,它接受一个像对象的通用树,该对象由像 children
这样的节点组成,而 optionaly 又可以有自己的 children
,第二个参数是一个函数predicate
,将当前访问的节点传递给过滤函数
我不太关心 tree
(children
除外)和 node
之类的对象内部的额外属性。为此我选择使用泛型来实现这个功能。下面是我的代码的简化版本。
interface NodeLike {
children?: NodeLike[];
}
interface TreeLike {
children: NodeLike[];
}
export function filterChildrenFromTree<T extends TreeLike, N extends NodeLike>(
t: T,
predicate: (n: N) => boolean
): T {
const newTree = {
children: t.children.filter(predicate)
};
return newTree;
}
不幸的是,打字稿在 return
行下给我以下错误:
Type '{ children: NodeLike[]; }' is not assignable to type 'T'.
如果声明 T
在这种情况下扩展了一个 TreeLike 对象,为什么当我 return 一个预期格式的对象时打字稿会抱怨?
T 扩展了 TreeLike,但 TreeLike 没有扩展 T。代码尝试 return TreeLike 而不是 T。
newTree 的类型应该是 T,但它是 '{ children: NodeLike[]; }'.
最简单的修复
const newTree = {
...t,
children: t.children.filter(predicate)
};
我可能误解了你想要什么,但对我来说,更通用的方法可能是用功能术语来描述你的树抽象,而不是每个节点上的已知 children
属性 .您可以定义以下函数类型,代表类型为 T[]|undefined
的子项的可选性质,但在这里我选择了一个空数组来表示相同的情况,因为它简化了逻辑:
type ChildSelector<T> = (item: T) => T[];
type Pred<T> = (item: T, index: number) => boolean;
type TreeAssembler<T> = (children: T[]) => T;
这现在允许您编写一个过滤函数,该函数对可过滤的树类型没有限制
export function filterChildrenFromTree<T>(
t: T,
childSelector: ChildSelector<T>,
predicate: Pred<T>,
treeAssembler: TreeAssembler<T>
): T {
const children = childSelector(t);
const newTree = treeAssembler(children.filter(predicate));
return newTree;
}
我正在尝试编写一个函数,它接受一个像对象的通用树,该对象由像 children
这样的节点组成,而 optionaly 又可以有自己的 children
,第二个参数是一个函数predicate
,将当前访问的节点传递给过滤函数
我不太关心 tree
(children
除外)和 node
之类的对象内部的额外属性。为此我选择使用泛型来实现这个功能。下面是我的代码的简化版本。
interface NodeLike {
children?: NodeLike[];
}
interface TreeLike {
children: NodeLike[];
}
export function filterChildrenFromTree<T extends TreeLike, N extends NodeLike>(
t: T,
predicate: (n: N) => boolean
): T {
const newTree = {
children: t.children.filter(predicate)
};
return newTree;
}
不幸的是,打字稿在 return
行下给我以下错误:
Type '{ children: NodeLike[]; }' is not assignable to type 'T'.
如果声明 T
在这种情况下扩展了一个 TreeLike 对象,为什么当我 return 一个预期格式的对象时打字稿会抱怨?
T 扩展了 TreeLike,但 TreeLike 没有扩展 T。代码尝试 return TreeLike 而不是 T。
newTree 的类型应该是 T,但它是 '{ children: NodeLike[]; }'.
最简单的修复
const newTree = {
...t,
children: t.children.filter(predicate)
};
我可能误解了你想要什么,但对我来说,更通用的方法可能是用功能术语来描述你的树抽象,而不是每个节点上的已知 children
属性 .您可以定义以下函数类型,代表类型为 T[]|undefined
的子项的可选性质,但在这里我选择了一个空数组来表示相同的情况,因为它简化了逻辑:
type ChildSelector<T> = (item: T) => T[];
type Pred<T> = (item: T, index: number) => boolean;
type TreeAssembler<T> = (children: T[]) => T;
这现在允许您编写一个过滤函数,该函数对可过滤的树类型没有限制
export function filterChildrenFromTree<T>(
t: T,
childSelector: ChildSelector<T>,
predicate: Pred<T>,
treeAssembler: TreeAssembler<T>
): T {
const children = childSelector(t);
const newTree = treeAssembler(children.filter(predicate));
return newTree;
}