【问题标题】:What's the correct way to use requireJS with typescript?将requireJS与打字稿一起使用的正确方法是什么?
【发布时间】:2013-11-19 18:40:18
【问题描述】:

我找到的示例 herehere 说要使用 module()。但是,当我编译时,我得到“警告 TS7021:'module(...)' 已弃用。请改用 'require(...)'。”

几个基本问​​题:

  1. 在使用 typescript 和 requireJS 时,如何同时访问一个类 .ts 文件来自另一个 .ts 文件,其中 requireJS 将加载第二个 文件并将第一个文件中的课程给我?
  2. 有没有办法使用两个 .ts 文件执行标准 requireJS 方法,其中顶部的 define() 加载第二个 ts 文件并返回它最后构建的对象?
  3. 与问题 #2 类似。从 java 脚本文件中,我可以使用 type 脚本文件上的 define() 构造来获取实例化对象吗?如果有,怎么做?

更新:以下给了我一个 tsc 编译错误:

///<reference path='../../libs/ExtJS-4.2.0.d.ts' />
///<reference path='../../libs/require.d.ts' />

import fdm = require("./file-definitions");
require(["../../scripts/ribbon"], function () {

export module Menu {

    export class MainMenu {

【问题讨论】:

    标签: requirejs typescript


    【解决方案1】:

    我会评论大卫对 basarat 的回答(关于模块和类)的回复,但我没有声誉。我知道这个问题已经过时了,但我没有在其他地方找到答案。

    我成功地使用了 basarat 的视频,并结合了其他一些资源,为 David Thielen 等课程找到了所需的内容。请注意,我不再有我的 ts 源文件的条目,但我确实有 amd-dependency 和 import 语句。在带有 palantir 的 TS 插件的 Eclipse 中,我的代码完成和从用法跳转到定义的能力仅使用 amd-dependency 和 import 语句。头文件仍然需要语句,因为它们与部署无关,仅由 TS 编译器使用。另请注意,.ts 文件扩展名用于引用语句,而不是 amd 和 import 语句。

    在 Utils.ts 我有:

    ///<reference path="headers/require.d.ts" />
    
    export function getTime(){
        var now = new Date();
        return now.getHours()+":"+now.getMinutes()+':'+now.getSeconds();
    }
    

    在 OntologyRenderScaler 我有:

    ///<reference path="headers/require.d.ts" />
    
    ///<reference path="headers/d3.d.ts" />
    ///<reference path="headers/jquery.d.ts" />
    
    ///<amd-dependency path="Utils" />
    
    import Utils = require('./Utils');
    
    export class OntologyRenderScaler {
    ...
    Utils.getTime();
    ...
    }
    

    在 OntologyMappingOverview.ts 我有:

    ///<reference path="headers/require.d.ts" />
    
    ///<reference path="headers/d3.d.ts" />
    ///<reference path="headers/jquery.d.ts" />
    
    ///<amd-dependency path="Utils" />
    ///<amd-dependency path="OntologyGraph" />
    ///<amd-dependency path="OntologyFilterSliders" />
    ///<amd-dependency path="FetchFromApi" />
    ///<amd-dependency path="OntologyRenderScaler" />
    ///<amd-dependency path="GraphView" />
    
    ///<amd-dependency path="JQueryExtension" />
    
    import Utils = require('./Utils');
    import OntologyGraph = require('./OntologyGraph');
    import OntologyRenderScaler = require('./OntologyRenderScaler');
    import OntologyFilterSliders = require('./OntologyFilterSliders');
    import GraphView = require('./GraphView');
    
    export class OntologyMappingOverview extends GraphView.BaseGraphView implements GraphView.GraphView {
        ontologyGraph: OntologyGraph.OntologyGraph;
        renderScaler: OntologyRenderScaler.OntologyRenderScaler;
        filterSliders: OntologyFilterSliders.MappingRangeSliders;
    ...
    this.renderScaler = new OntologyRenderScaler.OntologyRenderScaler(this.vis);
    ...
    }
    

    我(还没有!)让事情像上面建议的 codeBelt 那样工作,但我们在他的博客上进行的一次交流显示,如果我让他的方法工作(在文件底部使用 export MyClass),那么我不需要将导入的标识符与类名加倍。我想它会导出感兴趣的类而不是它定义的命名空间(隐式外部模块,即 TypeScript 文件名)。

    【讨论】:

    • 如果你想避免类名加倍(即 OntologyGraph.OntologyGraph),在 OntologyGraph.ts 中,你可以从类前面删除导出,而是在末尾添加一行文件:出口=本体图;那么在引用它的文件中就可以将其称为简单的OntologyGraph。
    • @mrcrowl 太棒了,我不认为有区别。我搜索了很多年试图阻止翻倍。
    • 现在引用 path= 已经过时,ES6 模块得到提升,但 ES6 模块没有得到广泛支持
    【解决方案2】:

    对于:

    在使用 typescript 和 requireJS 时,如何同时访问一个类 .ts 文件来自另一个 .ts 文件,其中 requireJS 将加载第二个 文件并给我第一个文件中的课程?有没有办法做到 带有两个 .ts 文件的标准 requireJS 方法,其中 define() 位于 顶部加载第二个 ts 文件并返回它构建的对象 最后?

    简单地说:

    // from file a.ts
    export class Foo{
    
    }
    
    // from file b.ts
    // import 
    import aFile = require('a')
    // use: 
    var bar = new aFile.Foo();
    

    并使用--module amd 标志编译这两个文件。

    对于:

    与问题 #2 类似。从 java 脚本文件,我可以使用 类型脚本文件上的 define() 构造以获取实例化 目的?如果有,怎么做?

    要使用 b.js 中的 a.ts,只需:

    // import as a dependency:
    define(["require", "exports", 'a'], function(require, exports, aFile) {
    
        // use:
        var bar = new aFile.Foo();
    });
    

    这类似于你编译 b.ts

    得到的结果

    【讨论】:

    • 你的意思是需要而不是定义?并且没有使用 aFile 并且 sFile 设置为 'a' 字符?我尝试了所有方法,但没有成功。
    • @DavidThielen 对不起,我的错,更新了生成的 js
    • 谢谢,我之前确实看过你的视频。它帮助了一些人,但我仍然坚持这一点,也许是因为我也在使用模块和类。
    • 应该承认var aFile = require('a')而不是import aFile = require('a')是行不通的('a'模块不会加入amd依赖列表)。
    【解决方案3】:

    你想要在你正在创建的类下面的导出语句。

    // Base.ts
    class Base {
    
        constructor() {
        }
    
        public createChildren():void {
    
        }
    }
    
    export = Base;
    

    然后导入并使用到另一个类中:

    // TestApp.ts
    import Base = require("view/Base");
    
    class TestApp extends Base {
    
        private _title:string = 'TypeScript AMD Boilerplate';
    
        constructor() {
            super();
        }
    
        public createChildren():void {
    
        }
    }
    
    export = TestApp;
    

    【讨论】:

      【解决方案4】:

      我一直在玩 typescript,试图将它集成到我们现有的 javascript/requirejs 项目中。 作为设置,我有 Visual Studio 2013 with Typescript for vs v 0.9.1.1。 Typescript 被配置为(在 Visual Studio 中)以 amd 格式编译模块。

      这是我发现的适合我的方法(当然可能有更好的方法)

      1. 使用 amd-dependency 告诉 typescript 编译器将所需的模块添加到必须加载的组件列表中
      2. 在要导出的类的构造函数中,使用 requirejs 的 require 函数来实际获取导入的模块(此时这是同步的,因为上一步)。为此,您必须参考 require.d.ts

      作为旁注,但由于在我看来它是打字稿必不可少的,并且因为它让我有点头疼,所以在示例中我展示了两种导出使用接口的类的方法。接口的问题是它们用于类型检查,但它们没有产生真正的输出(生成的 .js 文件是空的),它会导致类型为“私有类的导出”的问题 我找到了两种导出实现接口的类的方法:

      1. 只需向接口添加一个 amd 依赖项(就像在 Logger.ts 文件中一样) 并导出一个包含该类的新实例的类型化变量 导出的类可以直接消费(即myClass.log('hello'));
      2. 不要将 amd- 依赖添加到接口中(就像在 Import.ts 文件中一样) 并导出一个函数(即 Instantiate()),该函数返回一个类型为 any 的变量,其中包含该类的新实例 导出的类可以通过这个函数来消费(即 myClass.instantiate().log('hello'))

      似乎第一个选项更好:您不需要调用实例化函数,而且您可以使用一个类型化的类。缺点是 [empty] 接口 javascript 文件确实会传送到浏览器(但无论如何它都会缓存在那里,也许你甚至正在使用缩小,在这种情况下这根本不重要)。

      在接下来的代码块中,有 2 个 typescript 模块加载了 requires (amd):Logger 和 Import。

      ILogger.ts 文件

      interface ILogger {
          log(what: string): void;
      }
      

      Logger.ts 文件

      ///<reference path="./ILogger.ts"/>
      
      //this dependency required, otherwise compiler complaints of private type being exported
      ///<amd-dependency path="./ILogger"/>
      
      class Logger implements ILogger {
              formatOutput = function (text) {
                  return new Date() + '.' + new Date().getMilliseconds() + ': ' + text;
              };
      
              log = function (what) {
                  try {
                      window.console.log(this.formatOutput(what));
                  } catch (e) {
                      ;
                  }
              };
      }
      
      //this approach requires the amd-dependency above for the interafce
      var exportLogger: ILogger = new Logger();
      export = exportLogger;
      

      在另一个 ts 文件中使用 Logger.ts(Import.ts)

      ///<reference path="../../../ext/definitions/require.d.ts"/>
      
      ///<amd-dependency path="Shared/Logger"/>
      ///<amd-dependency path="./IImport"/>
      
      class _Import implements IImport{
          ko: any;
          loggerClass: ILogger;
      
          constructor() {
              this.ko = require('knockout');//require coming from require.d.ts (in external_references.ts)
              this.loggerClass = require('Shared/Logger');
          }
      
          init(vm: any) {
              this.loggerClass.log('UMF import instantiated...');
          }
      }
      
      ////Alternative Approach:
      ////this approach does not require adding ///<amd-dependency path="./IImport"/>
      ////this can be consumed as <imported_module_name>.instantiate().init();
      //export function instantiate() {
      //    var r : any = new _Import();// :any  required to get around the private type export error
      //    return r;
      //}
      
      //this module can be consumed as <imported_module_name>.init();
      var exported: IImport = new _Import();
      export = exported;
      

      IImport.ts 文件

      interface IImport {
          init(vm: any): void;
      }
      

      要直接从 javascript 使用 Import 模块,请使用类似的东西(对不起,我没有尝试过这个,但它应该可以工作)

      define (['Import'], function (import)
      {
          //approach 1
          import.init();
      
          ////approach 2
          //import.instantiate().init();
      });
      

      【讨论】:

      • 首先,谢谢。二、“export = exportLogger;”是什么意思做什么?
      • export 是模块返回给消费者的内容。这意味着“当另一个模块使用我时,这就是他得到的”
      • 哦,好的。我认为这在这里没有帮助,因为我不想返回一个对象。我只有一个包含一个静态函数的类,稍后我需要调用该静态函数。另外,如果我去掉了 export 关键字,那么它就会被模块名称绊倒。
      猜你喜欢
      • 2018-04-10
      • 2013-01-02
      • 1970-01-01
      • 2020-08-27
      • 2020-07-10
      • 2020-09-29
      • 1970-01-01
      • 2012-05-12
      • 1970-01-01
      相关资源
      最近更新 更多