如果函数f: (X => Y) | undefined
可能未定义,并且x: X
已定义,则我们可以使用可选的链接运算符?.
将f
应用于x
:
f?.(x) // ok, no problem if `f` is undefined
但是当定义了f: X => Y
并且可能未定义x: X | undefined
时;地图";8上的CCD_;可选的";x
:
f(?.x) // not valid syntax; Unclear what to do when `x` is undefined
我可以尝试实现pipeTo
来交换f
和x
的顺序,然后使其再次与?.
一起工作,如下所示:
function opt<X>(x: X | undefined): { pipeTo<Y>(f: (a: X) => Y): Y } | undefined {
return typeof x === 'undefined' ? undefined : {
pipeTo<Y>(f: (a: X) => Y): Y {
return f(x)
}
}
}
然后我可以将其用作opt(x)?.pipeTo(f)
,例如:
function square(n: number): number { return n * n }
for (const x of [42, undefined, 58]) {
console.log(opt(x)?.pipeTo(square))
}
对于将一个肯定存在的f
应用于一个可能未定义的x
,是否有任何不那么麻烦的标准解决方案?
澄清:";笨重的">:=任何迫使我写两次子表达式x
的内容,或者用无意义的辅助变量扰乱作用域的内容。
这就像您正在查看Nullable<T>
类型的操作(定义为
type Nullable<T> = T | null | undefined
)作为函子并且想要对其执行函子fmap
动作以将形式(x: X) => Y
的函数f
变成形式(x?: Nullable<X>) => Nullable<Y>
的另一函数。我不认为有任何内置功能会以这种方式运行,我也不能权威地谈论它在第三方库中的存在,但你可以很容易地自己编写:
const fmapNullable = <X, Y>(f: (x: X) => Y) =>
(x?: Nullable<X>): Nullable<Y> => x == undefined ? undefined : f(x);
然后使用它:
function square(n: number): number { return n * n };
for (const x of [42, undefined, 58]) {
console.log(fmapNullable(square)(x)?.toFixed(1))
// "1764.0";
// undefined;
// "3364.0"
}
从语法上讲,我不认为你能得到像可选链接运算符(?.
(那样简洁的表示法;TypeScript毕竟不是Haskell。你可以缩短";CCD_ 24";,但您仍然会应用一个函数,所以最多只能使用$_$(square)(x)
这样的函数。哦,好吧!
游乐场链接到代码
这看起来像数组,所以这里有一个的数组实现
function nonNullable<T>(v: T | null | undefined): v is T {return v != null}
class OneOrZeroArray<T> extends Array<T> {
pipe<V>(mapper: (v: T) => V) {
return this.map(mapper).filter(nonNullable)
}
pop(): T | undefined {
return super.pop();
}
static from<T>(item?: T | null | undefined): OneOrZeroArray<T> {
let a = new OneOrZeroArray<T>();
if (item != null) a.push(item);
return a;
}
}
function opt<T>(v: T | null | undefined) {return OneOrZeroArray.from(v)}
function square(n: number): number { return n * n }
for (const x of [42, undefined, 58]) {
console.log(
opt(x).pipe(square).pop()
)
}
某个人,某个地方,可能考虑过猴子补丁Function
:
Function.prototype.$ = function (x) {
return typeof x === 'undefined' ? undefined : this.apply(null, [x])
}
似乎有效,语法开销正好有两个字符:
function square(x) { return x * x }
square.$(42) // 1764
square.$(undefined) // undefined
请不要这样做。即使我们可以,也不意味着我们<em]应该>。
(此外,它是JS,因为我目前不想试图通过TS编译器压缩它(