TypeScript中的RequireJS模块声明

4

我最近升级到了TypeScript 0.9.5,编译时出现了新的错误。

我正在使用RequireJS定义一个AMD模块,如此处所述。

define('myModule', [
    'angular',
    'config'
    ], function (angular, config) {
        'use strict';

        ...
});

RequireJS的TypeScript定义文件中, RequireDefine 的定义如下:

/**
* Define a module with a name and dependencies.
* @param name The name of the module.
* @param deps List of dependencies module IDs.
* @param ready Callback function when the dependencies are loaded.
*   callback deps module dependencies
*   callback return module definition
**/
(name: string, deps: string[], ready: (...deps: any[]) => any): void;

然而,我遇到了以下错误:
error TS2082: Build: Supplied parameters do not match any signature of call target:
error TS2087: Build: Could not select overload for 'call' expression.

智能感知错误显示:
调用类型“(angular:any, config:any) => any”和“(...deps: any[]) => any”的签名不兼容。
定义文件是否不正确?在回调参数方面我犯了什么错误?
进一步信息:
将声明更改为以下内容,现在可以编译。
define('myModule', [
    'angular',
    'config'
    ], function (...args:any[]) {
        'use strict';

        ...
});

然而,转向单个参数对象肯定是一种倒退吗?这是定义文件还是TypeScript编译器的限制?

2个回答

4

这是定义文件还是TypeScript编译器的限制?

两者都有。这是TypeScript编译器的“限制”(限制之所以使用引号是因为它在此处强制执行有效约束),并且可以通过修改定义文件来解决。

实际上,重现此情况要简单得多:

function argLoving(fn: (...deps: any[]) => any){

}

argLoving(function(x,y){ // <- compile error

});

问题是 - 虽然您可以在声明或提供argLoving中使用x和y调用该函数 - 但它必须实际上接受varargs以避免破坏类型安全性。
想象一下以下情况:
function argLoving(fn: (...deps: any[]) => any){

}
function foo(x:any,y:any){

}
argLoving(foo);

现在很明显,argLoving 接受一个可以处理可变数量参数的函数,但是 foo 只能处理两个参数。这就是类型问题。
C# 解决这个问题的方式相当丑陋*(例如 Func),所以如果你想要一个快速且简单的修复方法 - 你可以在你的 .d.ts 文件中定义多个签名:
当然,这样编译没有问题:
function argLoving(fn: (x:any) => any)
function argLoving(fn: (x:any,y:any) => any)
function argLoving(fn: (x:any,y:any,z:any) => any)
function argLoving(fn: (x:any,y:any,z:any,a:any) => any)
function argLoving(fn: (...deps: any[]) => any){

}
function foo(x:any,y:any){

}
argLoving(foo); // this compiles now

* http://msdn.microsoft.com/en-us/library/bb534960(v=vs.110).aspx - 查看左侧所有ActionFunc的重载


更新:

在我在GitHub上开了一个问题后,DefinitelyTyped的作者提供了拉取请求,并针对此问题使用了与此处建议相同的解决方法https://github.com/borisyankov/DefinitelyTyped/issues/1434。这里进行讨论https://github.com/borisyankov/DefinitelyTyped/pull/1435


谢谢解释,现在清晰多了。然而,我不确定您建议的修复是否真的适用于RequireJS定义文件。对一个方法所需参数数量施加上限是可以接受的(如果你有>x,那么你做错了什么)。限制模块可能需要的“依赖项”数量可能更难以证明,考虑到现在鼓励模块化。 - Brett Postin
@BrettPostin 你说得对,但实际上你想要表达的是第一个传递的数组需要与函数获取的可变参数具有相同的长度限制。这是实际的限制,而在TypeScript中无法表达(尚未)。不过,C#现在已经支持1到31个参数的FuncAction,它们都被广泛使用,投诉水平也很低。你是否真的有超过31个约束条件的模块?就像我说的-我同意这是有问题的,但我认为它也非常实用。 - Benjamin Gruenbaum
这对我们来说不是问题,但由于定义文件是社区驱动的项目,也许RequireJS世界中的某个人会有所帮助!我将在GitHub上将其作为问题进行提交(https://github.com/borisyankov/DefinitelyTyped/tree/master/requirejs)。 - Brett Postin
@BrettPostin 我已经完成了 :) https://github.com/borisyankov/DefinitelyTyped/issues/1434 - Benjamin Gruenbaum

1

对于接受任何类型参数并返回任何类型的函数定义,新的推荐语法是:

function require(fn: Function){

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接