我有一个对象数组,每个项目都可以扩展{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数组?
答案 0 :(得分: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[];
希望有帮助。