请帮助我解决以下问题。我使用Visual Studio nodejs工具创建了默认的node.js应用程序,现在我正在尝试调用node.d.ts中声明的setTimeout函数。代码是这样的:
var timer: NodeTimer;
timer = setTimeout(somecallback, 1000);
但是代码没有编译说'Cannot convert 'Number' to 'NodeTimer''
据我所知,问题是它采用标准的setTimeout函数而不是从node.d.ts获取一个。
我尝试使用\\\<reference>
标记指定对node.d.ts的引用 - 这没有帮助。我如何明确声明我想从node.d.ts使用setTimeout?
我怀疑TS 0.9.5中引入的更改打破了这一点,在changelog中将其描述为:
简化了过载分辨率规则
描述:过载分辨率现在遵循更简单的算法。当多个重载适合给定的调用时,我们选择第一个适合而不是尝试找到“最适合”。
这意味着现在应该将具有重载的代码从最严格/更具体的过载手动排序到最松散。
可用的两个重载如下:
// in lib.d.ts
declare function setTimeout(handler: any, timeout?: any, ...args: any[]): number;
// in node.d.ts
declare function setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeTimer;
显然,第一个重载将始终匹配第二个重载可以匹配的所有内容,因此只要它是第一个被考虑的,它将始终是首选。
在存在两个.d.ts文件的情况下,文件的顺序定义了它们的相对重载顺序。通常,lib.d.ts始终排在第一位,因此它获得优先权。但是,如果您手动引用它,并确保引用在node.d.ts之后,那么后者将优先,您将最终得到正确的重载。
从命令行执行此操作非常简单 - 只需按所需顺序明确指定.d.ts文件即可。对于VS项目,您可以使用_references.ts执行相同的操作,如下所示:
/// <reference path="Scripts/typings/node/node.d.ts" />
/// <reference path="C:\Program Files (x86)\Microsoft SDKs\TypeScript\1.0\lib.d.ts" />
为避免像这样对绝对路径进行硬编码,您可能希望在Scripts / typings / node中的node.d.ts旁边的项目中创建lib.d.ts的本地副本。
您可能还想在discussion thread上关于TypeScript论坛上的这一变化,并与TS团队分享您的经验。
最简单有力的修复:
var timer: NodeTimer;
timer = <any>setTimeout(somecallback, 1000);
纯娱乐
我根据当前节点定义(https://github.com/borisyankov/DefinitelyTyped/blob/master/node/node.d.ts#L22)创建了一个小样本,它在typescript playground中运行良好
interface NodeTimer{
ref() : void;
unref() : void;
}
declare function setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeTimer;
var timer: NodeTimer;
timer = setTimeout(()=>{}, 1000);
我不知道你为什么会在发生冲突时发生冲突。仅供参考,冲突的setTimeout
在lib.d.ts
中定义,但也包含在TypeScript游乐场中,并且不会引起任何戏剧性。
如果您在timeout
或NodeJS中尝试使用'Cannot convert 'Number' to 'NodeTimer''
或'Cannot convert 'Number' to 'NodeJS.Timer''
,'Cannot convert 'Number' to 'NodeJS.Timeout''
或Type 'Timeout' is not assignable to type 'number'
等Browser »» Window
时遇到麻烦,可以使用这种类型安全的Window和NodeJS解决方案:
const timer: ReturnType<typeof setTimeout> = setTimeout(() => null, 1000);
clearTimeout(timer);