Typescript 类型保护和扩展联合类型?

Typescript 类型保护和扩展联合类型?,typescript,types,assert,extends,Typescript,Types,Assert,Extends,我有一个对象数组,其中每个项要么扩展{x:method}要么扩展{y:method},我想尝试将它们分开。我写了以下内容 export const refresh = < N extends HasRefresh | HasRefreshWithFoo, RefreshWithFoo extends HasRefreshWithFoo, RefreshNormal extends HasRefresh >( ns: N[], foos: Foo[] ) =>

我有一个对象数组,其中每个项要么扩展
{x:method}
要么扩展
{y:method}
,我想尝试将它们分开。我写了以下内容

export const refresh = <
  N extends HasRefresh | HasRefreshWithFoo,
  RefreshWithFoo extends HasRefreshWithFoo,
  RefreshNormal extends HasRefresh
>(
  ns: N[],
  foos: Foo[]
) => {
  const refreshWithFoo: RefreshWithFoo = ns.filter((n): n is RefreshWithFoo  =>
    n.x !== undefined
  ) 
}

给定一个包含扩展HasRefreshWithFoo或扩展HasRefresh的项的对象数组,如何用union分隔该数组,使一个数组只包含RefreshNormal和一个数组只包含RefreshWithFoo?

您可以通过对泛型类型进行另一个抽象来缩小编译器错误。
第二个抽象将负责按给定类型过滤数组

const filterByType = <T>(arr: any[], key: keyof T): T[] =>
    arr.filter(e => (<T>e)[key]) as T[];
没有任何抱怨。
我使用的是默认的tsconfig,我想这不会影响任何其他编译器配置。如果是,请告诉我

编辑
在某些情况下,如类型交叉点,您将需要多个关键点来检查。您可以简单地扩展该方法,方法是使用一个params键数组并检查所有键,如下所示

const filterByType = <T>(arr: any[], ...keys: (keyof T)[]): T[] =>
    arr.filter(e => keys.every(k => (<T>e)[k])) as T[];
const filterByType=(arr:any[],…keys:(keyof T)[]):T[]=>
arr.filter(e=>keys.every(k=>(e)[k]))作为T[];

希望能有所帮助。

这种方法很有效,但如果类型是交叉点或有多个键,我会遇到麻烦。有没有办法扩展它以实现T类型的所有键?您不必检查所有键,只需检查仅存在于您要检查的类型中的唯一键。在类型交叉的情况下,无法筛选特定类型。有两种类型,A和B,(A&B)的实例不再是A或B,所以按A或B进行过滤是没有意义的。我明白了,但是如果我们有filterByType(arr,'A'),我们实际上没有验证它也有B。在某些情况下,我需要过滤那些具有多种类型的交叉点,因为我可以有一个包含[val1:(A&B&C)、val2:(B&C)、val3:(C&A)]的数组,我想提取那些具有A&B的交叉点,然后过滤其中一个键将不起作用。我可能会为此提出一个新问题。嗯,也许你应该这样做。不过,我会更新答案以适应这种情况。
export const refresh = <
  N extends HasRefresh | HasRefreshWithFoo,
  RefreshWithFoo extends HasRefreshWithFoo,
  RefreshNormal extends HasRefresh
>(
    ns: N[], 
    foos: Foo[]
) => {
    const refreshWithFoo: RefreshWithFoo[] = filterByType<RefreshWithFoo>(ns, `x`);
}
const filterByType = <T>(arr: any[], ...keys: (keyof T)[]): T[] =>
    arr.filter(e => keys.every(k => (<T>e)[k])) as T[];