打字稿:如何从返回函数的输入参数推断高阶函数中的泛型类型

时间:2021-01-28 22:35:41

标签: typescript type-inference typescript-generics higher-order-functions currying

type FindCallback<T> = (value: T) => boolean;

type FindResult<T> = (arr: T[]) => T | undefined;

type FindFn = <T>(callback: FindCallback<T>) => FindResult<T>;

const find: FindFn = (callback) => {
    return (arr) => {
        for (let idx = 0; idx < arr.length; idx++) {
            if (callback(arr[idx])) {
                return arr[idx];
            }
        }
        return undefined;
    };
};

const myArray = [1, 5, 4, 9];
const result0 = find<number>((value) => value > 1)(myArray); // works, but explicitly defined the type 'number' in find<number>
const result1 = find((value: number) => value > 1)(myArray); // works, but explicitly defined the type 'number' in the callback (value: number)
const result2 = find((value) => value > 1)(myArray);         // my desired way of calling find(), but the callback parameter 'value' and 'result2' are both 'unknown'
//                              ^
//                      Object is of type 'unknown'.

我正在努力提高对 Typescript 和函数式编程的理解,但偶然发现了以下场景:

我有这个高阶 find 函数,它应该在数组中找到满足特定条件的第一个元素。

我现在的问题如下:

是否可以改进我的类型,以便可以从 T 中的值类型推断出我在 FindCallback 中使用的泛型类型 myArray,而无需将其明确定义为 number ?此外,find()() 的返回值应该与数组中的元素具有相同的类型,或者 undefined(如果没有找到元素)。

这是 TS Playground 的链接。

1 个答案:

答案 0 :(得分:2)

如果这是一个带有两个参数的函数:callbackarray 那么它会很简单。实际上,您有两个独立的功能。您无法根据传递给第二个函数的参数推断第一个函数的类型。

这种高阶函数结构意味着不需要立即调用返回的FindResult函数。 const mapper = find((value) => true) 的类型是什么?这是一个在 array 的 ...?如果不注释 value,您根本无法知道最终将使用什么类型的数组调用它。

只有当数组是函数的参数时,才能根据数组的类型进行推断。

type FindFn = <T>(callback: FindCallback<T>, arr: T[]) => T | undefined;

const find: FindFn = (callback, arr) => { ...

Playground Link