如何在字典中将eta减少的泛型函数作为参数传递?

时间:2014-01-06 18:55:50

标签: typescript

这是我的设置:

export interface Promised <d, e> {
    then<o, e>(
        haveData: (data: d) => o,
        haveError?: (error: e) => e
        ): Promised<o, e>;
}
export interface Problem {
    message: string;
}
export interface Nothing {
}
export function ignore<a>(value: a): a { return value; }
export var nothing: Nothing = {};
export function fail<a>(problem: Problem): a;
export function fail<a>(message: string): a;
export function fail(something: any): any {
    if (typeof something === 'string') {
        throw new Error(something);
    } else {
        throw new Error(something.message);
    }
};

我需要的是ignoreOrFail函数,如下所示:

export function ignoreOrFail<d>(promise: Promised<d, Problem>): Nothing {
    promise.then(ignore, fail); // <--- PROBLEM WITH 'fail'
    return nothing;
}

然而,它因为无法推断出fail函数的类型参数而中断:

Supplied parameters do not match any signature of call target:
    Call signatures of types 'typeof fail' and '(error: Problem) => Problem' are incompatible:
        Type '{}' is missing property 'message' from type 'Problem'.
        Type '{}' is missing property 'message' from type 'Problem'.    

如果我定义另一种类型参数是硬编码的方法,则可以修复此问题:

export function failAlong(problem: Problem): Problem {
    return fail<Problem>(problem);
};
export function ignoreOrFail<d>(promise: Promised<d, Problem>): Nothing {
    promise.then(echo, failAlong); // <---- WORKS THIS WAY
    return nothing;
}

但这是一件愚蠢的事情,不是吗?我认为可行的是给编译器一个这样的提示:

export function ignoreOrFail<d>(promise: Promised<d, Problem>): Nothing {
    promise.then(echo, fail<Problem>);
    return nothing;
}

但这似乎超出了语法。那么问题是:有没有办法将eta减少的通用函数指定为参数? PS: 对于非泛型函数,这不是一个问题(查看ignore)。

1 个答案:

答案 0 :(得分:1)

不支持您请求的语法,如下面的细分所示。您可以在此处发送请求(http://typescript.codeplex.com/workitem/list/basic

function foo<x>(arg:x){} // foo is x=>x    
function bar(arg:(a:number)=>number){} // arg is number=>number

bar(foo<number>); // Syntax not supported     
bar(foo); // This does work though

但是,如上所示,您不应该在简单的情况下出错。您收到错误的原因是因为您已经确定了类型参数a

PS:问题的简单再现:

declare function foo<x>(arg:number):x; // foo is number=>x    
function bar(arg:(a:number)=>number){} // arg is number=>number    
bar(foo); // FAIL