繁体   English   中英

TypeScript 中通用 `map` 函数的类型声明

[英]Type declaration of a generic `map` function in TypeScript

typescript-exercises 的练习 #14 中,您可以注释以下函数:

export function map(mapper, input) {
    if (arguments.length === 0) {
        return map;
    }
    if (arguments.length === 1) {
        return function subFunction(subInput) {
            if (arguments.length === 0) {
                return subFunction;
            }
            return subInput.map(mapper);
        };
    }
    return input.map(mapper);
}

我尝试使用泛型对其进行严格输入,但失败了:

type Apply<In, Out> = (element: In) => Out;

declare function subFunction<In2, Out2>(subInput: In2[]): Out2[];
declare function subFunction(): typeof subFunction;

export function map<In, Out>(): typeof map;
export function map<In, Out>(mapper: Apply<In, Out>): typeof subFunction;
export function map<In, Out>(mapper: Apply<In, Out>, input: In[]): Out[];

export function map<In, Out>(mapper?: Apply<In, Out>, input?: In[]): ((typeof map) | (typeof subFunction) | Out[]) {
    if (mapper === undefined) {
        return map;
    }
    if (input === undefined) {
        // Line 61 (the error) ahead
        return function subFunction(subInput?: In[]): ((typeof subFunction) | Out[]) {
            if (subInput === undefined) {
                return subFunction;
            }
            return subInput.map(mapper);
        };
    }
    return input.map(mapper);
}

错误是:

index.ts(61,9): error TS2322: Type '(subInput?: In[] | undefined) => Out[] | ...' 不能分配给类型 '{ <In2, Out2>(subInput: In2[]): Out2[]; (): 子函数类型; } | { <In, Out>(): typeof map; <In, Out>(映射器: Apply<In, Out>): { <In2, Out2>(subInput: In2[]): Out2[]; (): 子函数类型; }; <In, Out>(mapper: Apply<...>, input: In[]): Out[]; } | 出去[]'。 输入 '(subInput?: In[] | undefined) => Out[] | ...' 不能分配给类型 '{ <In2, Out2>(subInput: In2[]): Out2[]; (): 子函数类型; }'。 输入“输出[] | ((subInput?: In[] | undefined) => Out[] | ...)' 不能分配给类型 'any[]'。 输入 '(subInput?: In[] | undefined) => Out[] | ...' 缺少类型 'any[]' 的以下属性:pop、push、concat、join 和另外 25 个。

当我将subFunction @ line 61 的返回类型更改为any时,错误消失了。

我究竟做错了什么?

我认为问题在于使用declare关键字。 我不确定问题出在哪里,但是这里没有正确使用关键字。 它应该用于通知编译器存在名为subFunction的函数,但事实并非如此,因为subFunction实际上是在map中声明的。

您可以通过将声明替换为我在此处称为SubMap<In, Out>的另一种type来解决此问题。

type Apply<In, Out> = (element: In) => Out;
type SubMap<In, Out> = (subInput?: In[]) => SubMap<In, Out> | Out[];

export function map<In, Out>(): SubMap<In, Out>;
export function map<In, Out>(mapper: Apply<In, Out>): SubMap<In, Out>;
export function map<In, Out>(mapper: Apply<In, Out>, input: In[]): Out[];

export function map<In, Out>(mapper?: Apply<In, Out>, input?: In[]): typeof map | SubMap<In, Out> | Out[]
{
    if (mapper === undefined)
    {
        return map;
    }
    if (input === undefined)
    {
        return function subFunction(subInput?: In[]): SubMap<In, Out> | Out[]
        {
            if (subInput === undefined)
            {
                return subFunction;
            }
            return subInput.map(mapper);
        };
    }
    return input.map(mapper);
}

另一种选择是在map之外实际创建subFunction ,尽管这需要一些重构。

type Apply<In, Out> = (element: In) => Out;

function subFunction<In, Out>(mapper: Apply<In, Out>): typeof subFunction;
function subFunction<In, Out>(mapper: Apply<In, Out>, subInput: In[]): typeof subFunction | Out[];

function subFunction<In, Out>(mapper: Apply<In, Out>, subInput?: In[]): typeof subFunction | Out[]
{
    if (subInput === undefined)
    {
        return subFunction;
    }
    return subInput.map(mapper);
}

export function map<In, Out>(): typeof map;
export function map<In, Out>(mapper: Apply<In, Out>): typeof subFunction;
export function map<In, Out>(mapper: Apply<In, Out>, input: In[]): Out[];

export function map<In, Out>(mapper?: Apply<In, Out>, input?: In[]): typeof map | typeof subFunction | Out[]
{
    if (mapper === undefined)
    {
        return map;
    }
    if (input === undefined)
    {
        return subFunction(mapper);
    }
    return input.map(mapper);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM