首页 > 解决方案 > 如何制作一个泛型过滤器,返回泛型中传递的数组元素

问题描述

我有一个ParentChildAand扩展的接口ChildB

interface Parent {
  sharedProp: string,
}

interface ChildA extends Parent { 
  onlyInA: string,
}

interface ChildB extends Parent { 
  onlyInB: number
}

我有一个包含联合数组类型的数组:

const entities: (ChildA|ChildB)[] = [
  {
    sharedProp: "this will be B",
    onlyInA: "because Im a"
  }, {
    sharedProp: "this will be B",
    onlyInB: 12345
  }
]

我已经做了我想要的非通用函数:

const childrenWithCertainSharedProp = (sharedProp: string): ChildA[] => {
    return entities
        .filter(isChildA)
        .filter(e => e.sharedProp === sharedProp);
}

我可以console.log(childrenWithCertainSharedProp('xxx'));

这是一个演示。

但正如你所看到的,我将返回值设置为ChildA[],并且我可以对 . 执行相同的操作ChildB[]

我想要类似以下的东西,但我无法做到:

const childrenWithCertainSharedProp = <T>(sharedProp: string): T[] => {
    return entities
        .filter(/* filter depending on T */)
        .filter(e => e.sharedProp === sharedProp);
}

基本上我想要的是以某种方式一般地输入guard,以一种我确保如果我通过<ChildA>我将确保它只会过滤ChildA等等的方式。

标签: typescriptgenerics

解决方案


您还需要至少传递一个具有该类型的参数,因为在运行时打字稿将无法访问类型参数。

作为警告,这只会和你的 typeGuards 一样好。

const childrenWithCertainSharedProp = <T extends ChildA | ChildB>(arr: T[], sharedProp: string): T[] => {
  return arr.filter(e => e.sharedProp === sharedProp);
}

console.log(childrenWithCertainSharedProp(entities.filter(isChildA), 'xxx')[0].onlyInA);
console.log(childrenWithCertainSharedProp(entities.filter(isChildB), 'xxx')[0].onlyInB);

推荐阅读