首页 > 解决方案 > 如何通过传递的保护函数缩小泛型类型?

问题描述

Opt让我们考虑ts-opt包(它只是一个 Maybe/Option/Optional)并isNumber有一个类型保护 ( (x): x is number => ...)。

是否可以以通用方式实现(以及如何)方法someIf(使用任意类型保护,类型安全,无需用户指定已经在类型保护中的类型):

type A = number | string;
const x: A = 4;
const y: A = 'y';
opt(x)               // Opt<number | string>
  .someIf(isNumber); // Opt<number> (Some(4))
opt(y)               // Opt<number | string>
  .someIf(isNumber); // Opt<number> (None)

标签: typescriptgenericstype-narrowing

解决方案


实现这一点的一种方法(没有someIf作为原型函数)如下

type A = number | string;

const x: A = 4;
const y: A = "y";

const isNumber = (a: any): a is number => typeof a === "number";

const someIf = <T>(ot: Opt<any>, f: (x: any) => x is T): Opt<T> =>
  ot.caseOf(
    t => (f(t) ? opt(t) : none),
    () => none
  );

const ox = someIf(
  opt(x),
  isNumber
); // Opt<number> <- Some(4)

const oy = someIf(
  opt(y),
  isNumber
); // Opt<number> <- None

沙盒链接


这个想法很简单。折叠可选值,如果none,我们无事可做。否则,根据类型保护验证包装的值。如果守卫成功,只需返回值(现在缩小其类型),否则返回none


推荐阅读