我试着在打字稿中写一些免费的咖喱函数。这样做我确实发现了一个问题。
打字本似乎是立即评估类型,并在我的理解,不允许非常好的仓促功能。
让我用一个例子来说明,首先是非咖喱函数。
const fn = (x: number): string => null
function inline <T, U>(fn: (x: T) => U, src: T[]): U[]
function inline <T, U>(fn: (x: T) => U, src: Iterable<T>): Iterable<U>
function inline(fn: (x: any) => any, src: any): any {
return null
}
const iarr = inline (fn, [1, 2]) // <-- string[]
const iset = inline (fn, new Set([1, 2])) // <-- Iterable<string>一切就绪,iarr和iset键入正确。
现在让我们来讨论一下这个函数:
function pointfree <T, U>(fn: (x: T) => U): (src: T[]) => U[]
function pointfree <T, U>(fn: (x: T) => U): (src: Iterable<T>) => Iterable<U>
function pointfree(fn: (x: any) => any) {
return (src: any): any => null
}
const curried = pointfree (fn) // <-- (src: number[]) => string[]
const parr = curried ([1, 2]) // <-- string[]
const pset = curried (new Set ([1, 2]))
// ^^^^^^^^^^^^^^^
// Argument of type 'Set<number>' is not assignable to parameter of
// type 'number[]'.
// or without caching same error
const pset = pointfree (fn) (new Set([1, 2]))一旦到达pset,就会对pointfree (fn)进行评估,并自动将其转换为第一种重载类型,这是一个数字数组,即使没有缓存为curried
在fp中,需要部分应用功能是非常普遍的.提前感谢
发布于 2018-11-10 00:43:23
当不同的参数类型导致不同的返回类型时,过载非常有用。使用两个具有相同参数类型的不同重载签名是没有用的。那是因为,就像手册上说的:
编译器查看重载列表,然后继续进行第一次重载尝试使用提供的参数调用函数。如果找到匹配项,则选择此重载作为正确的重载。
在pointfree的定义中,参数列表对于每个重载都是相同的。这意味着编译器将始终选择第一个,如果它选择一个。
那么,怎样才是正确的方法呢?我建议使用一个返回重载函数的单个调用签名。如下所示:
// call signature, returns overloaded function
function pointfree<T, U>(fn: (x: T) => U): {
(src: T[]): U[],
(src: Iterable<T>): Iterable<U>
};
// implementation signature is the same as before
function pointfree(fn: (x: any) => any) {
return (src: any): any => null
}让我们使用它:
const curried = pointfree(fn)
// const curried: {
// (src: number[]): string[];
// (src: Iterable<number>): Iterable<string>;
// }现在您可以看到,curried是一个重载的函数,具有两个调用签名。因此,以下调用的行为与您预期的一样:
const parr = curried([1, 2]) // <-- string[]
const pset = curried(new Set([1, 2])) // <-- Iterable<string>好吧,希望能帮上忙。祝好运!
https://stackoverflow.com/questions/53234178
复制相似问题