如何通过传递的保护函数缩小泛型类型?
How to narrow a generic type via passed guard function?
让我们考虑来自 ts-opt 包的 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)
实现该目标的一种方法(无需 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
这个想法很简单。把optional值折叠起来,如果none
,我们就没事了。否则,根据类型保护验证包装的值。如果守卫成功,只需 return 值(现在缩小了它的类型),否则 return none
.
让我们考虑来自 ts-opt 包的 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)
实现该目标的一种方法(无需 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
这个想法很简单。把optional值折叠起来,如果none
,我们就没事了。否则,根据类型保护验证包装的值。如果守卫成功,只需 return 值(现在缩小了它的类型),否则 return none
.