在Meteor.js中使用Typescript模块

时间:2015-02-04 12:30:29

标签: meteor typescript

伙计们,我正在尝试做一些我认为应该简单的事情,但我必须做错事。我试图在我的流星应用程序中使用一个清晰​​的结构,它使用的是Typescript。

以下是我的要求:

  • 所有接口均可在客户端和服务器中使用
  • 某些类实现仅在服务器上可用
  • 我不想依赖文件加载顺序让我的应用程序正常工作
  • 我需要自己的模块不与全局对象冲突(例如Position类)
  • 我需要一个用于服务器的单片包含文件,一个用于客户端和服务器,一个用于客户端(不希望在我的文件之上包含10个包含)

我现在的设置就是这个

  • 服务器
    • 服务器book.ts
  • 客户端
  • 共享
    • collections.ts
  • 定义
    • 服务器
      • include.d.ts(包括此文件夹中的所有.d.ts文件)
      • server-book.d.ts(服务器特定的书籍实施)
    • 客户端
    • 共享
      • include.d.ts(此处包括所有.d.ts文件)
      • book.d.ts(图书界面定义)
      • collections.d.ts

在每个.d.ts文件中我有

module MyModule {
     interface Bla {}
};

在定义我所拥有的类的每个.ts文件中:

module MyModule {
     export class MyBla implements Bla {};
}

为类生成的所有.d.ts文件都是由tsc -d。

生成的

通过///< reference>包含没有.ts文件而只是.d.ts文件。

现在,当我运行它时,我得到一个错误,MyModule未定义:

/// <reference path="shared/include.d.ts"/>
/// <reference path="server/include.d.ts"/>
Meteor.startup(() => {
   var temp = new MyModule.ServerBook();
});

错误发生在MyModule上。

我做错了什么?这里适当的设置应该是什么?

谢谢!

5 个答案:

答案 0 :(得分:3)

我已经在blog处理了这个问题。我决定使用邪恶的eval命令,因为它给了我最简单的使用模块的可能性,直到出现更复杂的东西。

文件/lib/foo.ts位于子目录中,因为它必须在Bar之前加载。

eval('var Hugo = (this.Hugo || (this.Hugo = {})'); // this will override the automatically emitted var Hugo and assigns it with globally defined Hugo module 

module Hugo {
  export class Foo {
    foo():string {
      return 'foo'
    }
  }
}

档案/bar.ts

/// <reference path="lib/foo.ts"/>
eval('var Hugo = (this.Hugo || (this.Hugo = {})'); // this will override the automatically emitted var Hugo and assigns it with globally defined Hugo module 

module Hugo {
 export class Bar extends Foo {
    bar () : string {
      return 'bar';
    }
  }
}

档案/test.ts

/// <reference path="lib/foo.ts"/>
/// <reference path="bar.ts"/>

var m = new Hugo.Bar();
console.log(m.bar());
console.log(m.foo());

如上所述here,对于类,解决方案更简单:

class ExportedClass {
    variable : int;
} 
this.ExportedClass = ExportedClass;

答案 1 :(得分:1)

定义文件应使用declare关键字。如果您没有使用此关键字,通常会收到错误。

declare module MyModule {
     export interface Bla {}
}

declare module MyModule {
    export class MyBla implements Bla {

    }
}

还值得检查ServerBook类是否包含export关键字(就像示例中的MyBla一样)。

答案 2 :(得分:0)

经过大量的试验和错误后,到目前为止我的调查结果如下:

使用typescript“module”关键字并不适合Meteor。我想目前你不能使用它(或者变通办法对我来说太复杂了)。

但是,您可以做以下事情:

假设您要使用包A来定义要公开的类ClassToExport。

class ClassToExport {
  getFoo(){
    return "foo";
  }
}

请注意你不能this.ClassToExport = ClassToExportapi.export('ClassToExport')或者ClassToExport在包A的全局范围内不可用,因此需要一个模块/命名空间来导出您的类,我们将在下面看到。

现在,为了让您的包的使用者可以使用该类,您必须创建一个名称空间,它将等同于内部模块的“module”typescript关键字。

让我们写一下:

declare var packageA; //so that the compiler doesn't complain about undeclared var
packageA = packageA || {}; //so that this namespace can be reused for the entire package
packageA.ClassToExport = ClassToExport; //the actual export

现在,别忘了写 包A的package.js中的api.export('packageA')

如果您有要使用ClassToExport的包B,则在包B中写:

var cte = new packageA.ClassToExport();

不要忘记在包B的package.js中使用api.use包A.

如果您不想在每次使用该类时编写命名空间,也可以在使用文件的顶部写下var ClassToExport = packageA.ClassToExport;

如果您只需要一个全局类打包,而不导出它,那么您只需执行以下操作:

this.ClassToExport = ClassToExport

再次api.export('ClassToExport'),或者它不再在包中提供。

这样,我认为内部打字稿模块的功能(导出/导入)就在那里。

答案 3 :(得分:0)

如果你不害怕gulp构建,我已经准备了一个打字稿样板项目,它允许你在你的应用程序中轻松使用打字稿,而不是依赖于包。

https://github.com/tomitrescak/meteor-boilerplate-typescript

答案 4 :(得分:0)

随机的想法,扩展Meteor而不是Window。

Meteor.yournamespace = Meteor.yournamespace || {};
Meteor.yournamespace.myclass = new MyClass();

Meteor.yournamespace.MyClass = MyClass();

我认为这比直接进入窗口对象恕我直言的侵入性小。我的两分钱。

现在你可以Meteor.yournamespace.MyClass:P

- 编辑

然后你可以创建一个meteor-extend.d.ts文件,并执行以下操作:

/// <reference path="main.d.ts" />
declare module Meteor {
    var yournamespace: any;
}

现在,您可以在<any>之前删除Meteor,并且不会投诉。