简体   繁体   English

类型保护函数的泛型

[英]Generic for type guard function

I'd like to create function which filters list of two types into two separate lists of unique type.我想创建一个函数,将两种类型的列表过滤成两个单独的独特类型列表。 I've succeed to create it with hardcoded types:我已经成功地使用硬编码类型创建了它:

interface TypeA {
  kind: 'typeA';
}
interface TypeB {
  kind: 'typeB';
}
filterMixedList(mixedList$: Observable<(TypeA | TypeB)[]>): Observable<TypeA[]> {
  return mixedList$.pipe(
    map(items => items
      .filter((item): item is TypeA => item.kind === 'typeA')),
  );
}

But is there way to create generic to avoid hardcoding?但是有没有办法创建通用来避免硬编码? Please, help.请帮忙。

PS: here is the minimal reproducible example: stackblitz PS:这是最小的可重现示例: stackblitz

One way to make this generic is to pass in the type guard function.使此通用的一种方法是传入类型保护函数。 That would look like this:那看起来像这样:

function typeFromMixedList<T, U extends T>(
  mixedList$: Observable<T[]>,
  guard: (item: T) => item is U
): Observable<U[]> {
  return mixedList$.pipe(map(items => items.filter(guard)));
}

Or, if you know that the type you are checking is a discriminated union , you can pass in the discriminant key and the value to check:或者,如果您知道要检查的类型是一个判别 union ,您可以传入判别键和要检查的值:

function typeFromDiscriminatedUnionList<
  T,
  K extends keyof T,
  V extends (T[K]) & (string | number | undefined | null)
>(
  mixedList$: Observable<T[]>,
  key: K,
  val: V
): Observable<Extract<T, { [P in K]?: V }>[]> {
  return mixedList$.pipe(
    map(items =>
      items.filter(
        (item): item is Extract<T, { [P in K]?: V }> => item[key] === val
      )
    )
  );
}

Either way should work for your example:无论哪种方式都适用于您的示例:

typeFromMixedList(of([a, b]), (x): x is TypeA => x.kind === "typeA").subscribe(
  v => (dataDivA.innerHTML = JSON.stringify(v))
);

typeFromDiscriminatedUnionList(of([a, b]), "kind", "typeB").subscribe(
  v => (dataDivB.innerHTML = JSON.stringify(v))
);

Okay, hope that helps;好的,希望有帮助; good luck!祝你好运!

Stackblitz link to code Stackblitz 代码链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM