TypeScript中精确重载的函数调用

时间:2014-05-02 12:07:40

标签: angularjs typescript overloading

我是TypeScript的新手,并尝试将其与AngularJS一起使用。这是一个困扰我的情况,因为我无法从编译器中得到错误。

在Angular(AFAIK)中,资源提供程序具有get()方法,该方法返回T的实例,T是类型参数。此方法有许多其他重载,可以接受paramsdata参数,可能还有成功和带有这样签名的错误处理程序:

interface IResourceSuccessCallbackFunction<T> {
    (value: T, responseHeaders: Array<string>): void;
}

interface IResourceErrorCallbackFunction {
    (httpResponse: string): void;
}

我从 corresponding declaration file at DefinitelyTyped 中获取灵感,为get函数提供了这些重载:

interface IResourceClass<T> {
    get(): T;
    get(dataOrParams: any): T;
    get(dataOrParams: any, success: IResourceSuccessCallbackFunction<T>): T;
    get(success: IResourceSuccessCallbackFunction<T>, error?: IResourceErrorCallbackFunction): T;
    get(params: any, data: any, success?: IResourceSuccessCallbackFunction<T>, error?: IResourceErrorCallbackFunction): T;
}

我的问题是这些定义允许我写这样的东西:

var resourceService: IResourceClass<number> = null;
var res1 = resourceService.get({ id: 1000 }, function() {
    console.log("fail");
});
var res2 = resourceService.get(function(p: Phone) {
    console.log(p);
}, function() {
    console.log("fail");
});

显然,对于res1,程序员通过将错误处理程序作为第二个参数传递出错,忘记了成功处理程序;对于res2,假定的成功处理程序接受错误的类型Phone而不是number

现在,我知道为什么这两个调用编译并且有效:最后一个重载版本总是匹配,因为它允许两个any参数和两个可选参数,这些都不存在。所以我正在寻找一种方法来定义可以捕获这些错误的重载变体。例如,将any替换为会说“不是函数”的类型,或者通过其他一些技巧替换。

这可能吗?

1 个答案:

答案 0 :(得分:1)

如果可能,请使用any删除重载。我不确定这是否适用于这种情况;这取决于API的工作原理。

res1将永远是正常的,因为你不是必需的来使用TypeScript中的参数(想象一下,如果必须对Array进行三参数回调,那会有多烦人#的forEach)。

对于res2,您有时可以通过添加“陷阱”重载来改善这种情况:

interface IResourceClass<T> {
    get(): T;
    get(success: IResourceSuccessCallbackFunction<T>, error?: IResourceErrorCallbackFunction): T;
    get(otherFunction1: (...a: any[]) => void, otherFunction2: (...a: any[]) => void): { YOU_HAVE_FAILED: {}; };
    get(dataOrParams: any): T;
    get(dataOrParams: any, success: IResourceSuccessCallbackFunction<T>): T;
    get(params: any, data: any, success?: IResourceSuccessCallbackFunction<T>, error?: IResourceErrorCallbackFunction): T;
}

var resourceService: IResourceClass<number> = null;
var res1 = resourceService.get({ id: 1000 }, function() {
    console.log("fail");
});
// res2: { YOU_HAVE_FAILED: {} }
var res2 = resourceService.get(function(p: Phone) {
    console.log(p);
}, function() {
    console.log("fail");
});

这不会立即出现编译错误,但res2的任何实际用法都是错误的。