我对 Ramda 的类型定义做了一些研究,因为我很好奇如果谓词函数实际上是类型保护,它们是如何处理类型的。事实证明,他们不使用类型保护来缩小类型。
请参阅DefinitelyTyped 代码。
顺便说一句,那里的评论实际上使他们给出的类型定义无效:
如果没有任何谓词匹配,则 fn 返回 undefined。
但是类型声明它返回一个R
not R | undefined
。我尝试cond
使用实用程序使用等效类型来实现fp-ts
,因为正如一些评论者指出的那样,它看起来不像fp-ts
内置等效于 cond。
像这样的东西对你有用吗?
import { reduce } from "fp-ts/lib/Array";
import { alt, some, none, fold, Option } from "fp-ts/Option";
import { pipe } from "fp-ts/lib/function";
type CondPair<T extends any[], R> = [
(...args: T) => boolean,
(...args: T) => R
];
const cond = <T extends any[], R>(pairs: Array<CondPair<T, R>>) => (
...args: T
): R | undefined =>
pipe(
pairs,
reduce(
none,
(prev: Option<R>, [pred, res]: CondPair<T, R>): Option<R> =>
pipe(
prev,
alt(() => (pred(...args) ? some(res(...args)) : none))
)
),
fold(
() => undefined,
(r) => r
)
);
enum abcd {
a,
b,
c,
d
}
const is = <T>(t: T) => (x: unknown) => t === x;
function isResultA(a: abcd) {
return 1;
}
function isResultB(b: abcd) {
return 2;
}
function isResultC(c: abcd) {
return 3;
}
function isResultD(d: abcd) {
return 4;
}
const getCaseResult = cond([
[is(abcd.a), isResultA],
[is(abcd.b), isResultB],
[is(abcd.c), isResultC],
[is(abcd.d), isResultD]
]);
for (let x of [abcd.a, abcd.b, abcd.c, abcd.d]) {
console.log(getCaseResult(x));
} // Logs 1, 2, 3, 4 respectively