【问题标题】:Generic for type guard function类型保护函数的泛型
【发布时间】:2020-06-27 13:30:10
【问题描述】:

我想创建一个函数,将两种类型的列表过滤成两个唯一类型的单独列表。我已经成功地用硬编码类型创建了它:

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')),
  );
}

但是有没有办法创建通用以避免硬编码?请帮忙。

PS:这是最小的可重现示例: stackblitz

【问题讨论】:

  • 泛型可以依赖kind 属性吗?如果不是,如何区分?
  • 两种类型都有,但我不知道它如何与泛型或类型保护连接......简单的泛型对我来说很清楚,但是类型保护 - 太复杂了(PS:高度赞赏所有有关此的文档。
  • 抱歉,我的问题可能不清楚。此问题的解决方案是否可以假设泛型函数仅用于具有区分它们的kind 属性的类型?
  • 类型保护仅用于缩小 TS 在编译时知道的类型。但是,在您的情况下,您需要一个在运行时检查类型的测试。那时类型系统不存在,因此您只能对它们进行硬编码或将这些类型具体化为更具体的东西,例如类或变量。
  • 有一种方法可以将其生成,但我的环境中没有您的依赖项;您能否编辑此代码以形成在独立 IDE 中工作的 minimal reproducible example 提供指向配置了相关依赖项的 Web IDE 的链接? TypeScript playground 不容易让你从rxjs/operators 导入,所以我是????‍♂️。祝你好运!

标签: typescript typescript-generics


【解决方案1】:

使这个通用化的一种方法是传入类型保护函数。看起来像这样:

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)));
}

或者,如果您知道要检查的类型是discriminated 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
      )
    )
  );
}

任何一种方式都适用于您的示例:

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))
);

好的,希望对您有所帮助;祝你好运!

Stackblitz link to code

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-10
    • 2020-09-16
    • 2022-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多