如何为具有构造函数的复杂外部commonjs模块(如imap)编写TypeScript声明文件?

这个问题是我早期的一个改进: 如何为具有构造函数的外部commonjs模块编写TypeScript声明文件?

我试图为imap模块编写一个声明文件: – imap on npm – node-imap这个文件应该是什么样的?

在没有find我上面提到的原始问题的满意答案之后,我意识到这个语言有一些相互竞争的特征:

  • 任何导出或导入都会使模块成为外部模块
  • 似乎没有办法从具有(模块级)构造函数的外部模块导出多个实体,因此共享实体必须位于模块外(环境)。
    看我以前的问题(上面)。
  • 没有办法将外部模块导入到声明模块之外的声明文件中
    下面的模式是不允许的: import fs = require('fs'); declare module 'A' {} import fs = require('fs'); declare module 'A' {}

这是我到目前为止的声明文件:

 interface IIMAPAccount { user: string; password: string; host: string; port: number; tls?: boolean; } interface IEMail { mail: any; } interface ICriteria { // The following message flags are valid types that do not have arguments: ALL: void; // All messages. ANSWERED: void; // Messages with the Answered flag set. DELETED: void; // Messages with the Deleted flag set. DRAFT: void; // Messages with the Draft flag set. FLAGGED: void; // Messages with the Flagged flag set. NEW: void; // Messages that have the Recent flag set but not the Seen flag. SEEN: void; // Messages that have the Seen flag set. RECENT: void; // Messages that have the Recent flag set. OLD: void; // Messages that do not have the Recent flag set. This is functionally equivalent to "!RECENT" (as opposed to "!NEW"). UNANSWERED: void; // Messages that do not have the Answered flag set. UNDELETED: void; // Messages that do not have the Deleted flag set. UNDRAFT: void; // Messages that do not have the Draft flag set. UNFLAGGED: void; // Messages that do not have the Flagged flag set. UNSEEN: void; // Messages that do not have the Seen flag set. // The following are valid types that require string value(s): BCC: any; // Messages that contain the specified string in the BCC field. CC: any; // Messages that contain the specified string in the CC field. FROM: any; // Messages that contain the specified string in the FROM field. SUBJECT: any; // Messages that contain the specified string in the SUBJECT field. TO: any; // Messages that contain the specified string in the TO field. BODY: any; // Messages that contain the specified string in the message body. TEXT: any; // Messages that contain the specified string in the header OR the message body. KEYWORD: any; // Messages with the specified keyword set. HEADER: any; // Requires two string values, with the first being the header name and the second being the value to search for. If this second string is empty, all messages that contain the given header name will be returned. // The following are valid types that require a string parseable by JavaScripts Date object OR a Date instance: BEFORE: any; // Messages whose internal date (disregarding time and timezone) is earlier than the specified date. ON: any; // Messages whose internal date (disregarding time and timezone) is within the specified date. SINCE: any; // Messages whose internal date (disregarding time and timezone) is within or later than the specified date. SENTBEFORE: any; // Messages whose Date header (disregarding time and timezone) is earlier than the specified date. SENTON: any; // Messages whose Date header (disregarding time and timezone) is within the specified date. SENTSINCE: any; // Messages whose Date header (disregarding time and timezone) is within or later than the specified date. //The following are valid types that require one Integer value: LARGER: number; // Messages with a size larger than the specified number of bytes. SMALLER: number; // Messages with a size smaller than the specified number of bytes. // The following are valid criterion that require one or more Integer values: UID: any; // Messages with UIDs corresponding to the specified UID set. Ranges are permitted (eg '2504:2507' or '*' or '2504:*'). } interface IFetchOptions { markSeen: boolean; // Mark message(s) as read when fetched. Default: false struct: boolean; // Fetch the message structure. Default: false envelope: boolean; // Fetch the message envelope. Default: false size: boolean; // Fetch the RFC822 size. Default: false modifiers: any; // Fetch modifiers defined by IMAP extensions. Default: (none) bodies: any; // A string or Array of strings containing the body part section to fetch. Default: (none) Example sections: } declare module "imap" { import events = require('events'); import EventEmitter = events.EventEmitter; interface IMAPFetch extends EventEmitter { } class IMAP extends EventEmitter { constructor(account : IIMAPAccount); connect(); openBox(name : string, flag : boolean, cb : (err : Error, box) => void); search(criteria : ICriteria, cb : (error : Error, uids : string[]) => void); fetch(source : any, object : IFetchOptions) : IMAPFetch; } var out: typeof IMAP; export = out; } 

理想情况下,所有的接口都将在模块“imap”内部定义,所以不存在全球范围的污染。

理想情况下,所有的接口都将在模块“imap”内部定义,所以不存在全球范围的污染

代替:

 interface IFetchOptions { markSeen: boolean; // so on } interface ICriteria { ALL: void; } 

请执行下列操作

 module imap { interface IFetchOptions { markSeen: boolean; // so on } interface ICriteria { ALL: void; } } 

而你只用imap污染全球范围。 这是一个非初始化模块,只能用于types信息。

参考:看看鬼模块 : http : //definitelytyped.org/guides/best-practices.html

在继续调查这个问题之后,我编写了定义文件,但还没有find一种方法将模块中的所有接口都放在里面,以免污染全局范围。

我将定义文件提交给DefinitelyTyped,并可以在这里查看: https : //github.com/psnider/DefinitelyTyped/commit/460bb6d63e349918b20e49d7a62f3d2a7c2aea0a


EDITED

感谢basarat指引我朝着正确的方向发展,尽pipe我无法把它缝合在一起,直到我发现了更多的遗漏片段。

我回顾了其他的答案和定义文件,发现了一个似乎可行的方法,并更新了我的pull请求: https : //github.com/borisyankov/DefinitelyTyped/pull/3324

我在imap.d.ts中使用了这个模式:

 declare module IMAP { export interface Config {} export class Connection { constructor(config : Config); } } declare module "imap" { var out: IMAP.Connection; export = out; } 

IMAP是一个非初始化模块,正如basarat所build议的那样,它使得这些接口可以在IMAP命名空间中访问。

然后在使用imap模块的代码中, example.ts

 /// <reference path='imap.d.ts' /> // brings module IMAP into scope import Imap = require('imap'); // gets the connection class var conn = new Imap({/* omitted for brevity*/}); // creates an imap connection