如何导出和导入类型定义?

时间:2014-03-04 06:48:12

标签: node.js typescript

我一直在使用TypeScript,模块系统对我来说仍然是一个谜。

我有这个类型定义文件(appComponents.d.ts):

/// <reference path="./authentication/API.d.ts"/>

import express = require('express');

declare module appComponents {
    export interface IComponents {
        application: express.Application;
        authenticationService: MyApp.IAuthenticationService;
        // and so on ...
    }
}

和这个文件(index.ts):

/// <reference path="./appComponents.d.ts"/>

import express = require('express');
import mssql = require('mssql');

function initComponents(): appComponents.IComponents {

    // Components initialized here ...
}

两个问题:

  1. 为什么我必须使用

    import express = require('express');

    而不是

    /// <reference path="./path/to/definitely-typed/express/express.d.ts"/>

    要避免error TS2095: Could not find symbol 'express'.?毕竟,这只是一个类型定义文件,它不会生成任何JavaScript,具体取决于另一个不生成JavaScript的类型定义文件中的类型。

  2. 为什么index.ts导致error TS2095: Could not find symbol 'appComponents'.?当我这样做时:

    import appComponents = require('./appComponents');

    为什么会导致error TS2094: The property 'IComponents' does not exist on the value of type 'appComponents'.

  3. 使用TypeScript 0.9.7.0。

2 个答案:

答案 0 :(得分:3)

  
      
  1. )为什么我必须使用
  2.   

import express = require('express'); 代替 /// <reference path="./path/to/definitely-typed/express/express.d.ts"/>

实际上你需要使用两个

/// <reference path="./path/to/definitely-typed/express/express.d.ts"/>
import express = require('express');

您可能在API.d.ts中有引用,或者只是在您的visual studio项目中包含express.d.ts

工作原理https://github.com/borisyankov/DefinitelyTyped/blob/master/express/express.d.ts#L15包含declare module "express" {这会告诉打字稿要提供的内容(此文件中包含export的内容:https://github.com/borisyankov/DefinitelyTyped/blob/master/express/express.d.ts当有人时是import / requireimport express = require('express')这些在打字稿中被称为外部模块,可以是amd / commonjs

  

为什么index.ts导致错误TS2095:找不到符号'appComponents'

因为您要声明内部模块并尝试将其作为外部模块导入。

PS:关于外部/内部模块的视频:http://www.youtube.com/watch?v=KDrWLMUY0R0&hd=1

<强>更新

  

你说我问题中的一个模块是内部模块:

仅供参考:declare module appComponents {使appComponents成为内部模块。如果要声明外部模块并使用declare module "appComponents" {,则应该import appComponents = require('appComponents');但不要。它不是你想要的。

  

为什么index.ts导致错误TS2095:找不到符号'appComponents'。?

因为appComponents.d.ts执行import它也成为外部模块。您应该将declare module appComponents {等移动到没有外部模块的文件中,然后使用///<reference

答案 1 :(得分:0)

这就解决了我的问题(#2):

不要创建.d.ts文件作为分离接口和类实现的方法。相反,在interface个文件中定义.ts。当一个类及其实现的接口位于不同的文件中时,require interface模块中的class模块。这也适用于不由类实现的接口,即用于强类型变量的接口。

示例:

// IAppComponents.ts

/// <reference path="../DefinitelyTyped/express/express.d.ts"/>

import express = require('express');
import IAuthenticationService = require('./services/IAuthenticationService')

interface IAppComponents {
    application: express.Application;
    authenticationService: IAuthenticationService;
}
export = IAppComponents;
// IAuthenticationService.ts

import ILoginCallback = require('./ILoginCallback');
import ILogoutCallback = require('./ILogoutCallback');

interface IAuthenticationService {
    login(user: string, pass: string, callback: ILoginCallback) void;
    logout(sessionToken: string, callback: ILogoutCallback): void;
}
export = IAuthenticationService;
// AuthenticationService.ts

import IAuthenticationService = require('./IAuthenticationService');
import ILoginCallback = require('./ILoginCallback');
import ILogoutCallback = require('./ILogoutCallback');

// We can't import this, because it's a js module with no matching type definition.
var mssql = require('mssql');

class AuthenticationService implements IAuthenticationService {
    login(user: string, pass: string, callback: ILoginCallback): void {
        // Implementation goes here ...
    }

    logout(sessionToken: string, callback: ILogoutCallback): void {
        // Implementation goes here ...
    }
}
export = AuthenticationService;

这种方法很有用,但有一点需要注意:TypeScript编译器为每个.js(但不是.ts)文件生成.d.ts个文件,即使.ts文件包含只有接口,导致生成空.js个文件。我现在可以忍受这种情况,但我希望有一天TypeScript团队能够做到这一点。