类型保护并扩展联合类型吗?

问题描述 投票:0回答:1

我有一个对象数组,其中每个项目都扩展为{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
  ) 
}

但是我遇到了错误

A type predicate's type must be assignable to its parameter's type.
  Type 'RefreshNormal' is not assignable to type 'N'.

给出一个包含对象的数组,这些对象包含扩展HasRefreshWithFoo或扩展HasRefresh的项目,如何用联合将数组分开,以使我只有一个RefreshNormal数组,而只有RefreshWithFoo的数组?

typescript types assert extends
1个回答
1
投票

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

const filterByType = <T>(arr: any[], key: keyof T): T[] =>
    arr.filter(e => (<T>e)[key]) as T[];

[Typescript guide of how to type guard an instance之后,我们被迫指定哪个键来检查是否有效地完成了转换(我们筛选所依据的类型中的唯一键)。

因此,我们现在可以按RefreshWithFoo过滤函数

export const refresh = <
  N extends HasRefresh | HasRefreshWithFoo,
  RefreshWithFoo extends HasRefreshWithFoo,
  RefreshNormal extends HasRefresh
>(
    ns: N[], 
    foos: Foo[]
) => {
    const refreshWithFoo: RefreshWithFoo[] = filterByType<RefreshWithFoo>(ns, `x`);
}

没有任何编译器抱怨。好吧,我使用默认的tsconfig,我认为这不会与其他任何编译器配置有关。如果是这样,请告诉我。

编辑在某些情况下,例如类型交集,您将需要多个按键来进行检查。您可以通过期望键的params数组来扩展方法,然后检查所有键,就像这样]

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

希望有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.