如何在TypeScript中按类型筛选对象数组

nkoocmlb  于 2023-01-10  发布在  TypeScript
关注(0)|答案(2)|浏览(192)

我使用了以下函数,通过对象的type属性过滤对象数组:

export const retrieveLayoutChangeActions = (data: GetOperations['included']) =>
  data.filter(d => d.type === 'layoutChangeAction') as LayoutChangeAction[];

data参数可以包含LayoutChangeAction[]以外的类型,也可以不包含(LayoutChangeAction | Product)[]。如何扩展类型定义,使其支持任何类型,只要它包含LayoutChangeAction
我试过使用仿制药,

export const retrieveLayoutChangeActions = <T extends LayoutChangeAction>(data: T[]) =>
  data.filter(d => d.type === 'layoutChangeAction') as LayoutChangeAction[];

但结果是TS2345: Argument of type '(LayoutChangeAction | Product)[]' is not assignable to parameter of type 'LayoutChangeAction[]'.
类型定义很大,但下面是使每个类型唯一的属性:

interface LayoutChangeAction extends BaseResponse<'layoutChangeAction'> {
  type: 'layoutChangeAction';
  /* unique attributes... */
}

interface Product extends BaseResponse<'product'> {
  type: 'product';
  /* unique attributes... */
}
nbysray5

nbysray51#

你可以说T必须是BaseResponse,那么data可以是(T | LayoutChangeAction)[]类型(这意味着数组必须有LayoutChangeActions):

export const retrieveLayoutChangeActions = <T extends BaseResponse<any>>(data: (T | LayoutChangeAction)[]) =>
  data.filter(d => d.type === 'layoutChangeAction') as LayoutChangeAction[];

使用filter时,可以使用类型 predicate 而不是Assert:

data.filter((d): d is LayoutChangeAction => d.type === 'layoutChangeAction');
mfuanj7w

mfuanj7w2#

如果类型是您的区分因素,则可以使用{ type: string }[]作为数据参数。
你确定你需要检索布局变化函数吗?.filter(isLayoutChange)更有表现力。

function isLayoutChange(t: { type: string }): t is Layout change {
  return t.type === 'layoutChangeAction'
}

t是Layout change是类型保护。在返回true的代码路径中,t的范围缩小到LayoutChange。

相关问题