打字稿中的依赖关系解析

时间:2016-04-27 14:54:21

标签: typescript

我有一个大型的Typescript项目,它被连接到一个JS文件中进行部署。 确保以正确的连接顺序给出文件的正确方法是什么?有太多的文件可以手动尝试和维护。

如果文件A中的类依赖于文件B中的类,则生成的连接文件中的类的排序很重要。如果文件B出现在文件A之后,则在运行时无法解析该类。

这肯定是一个常见的问题,应该有一个简单的解决方案。 一个警告是我使用命名空间而不是模块。我不确定在整个项目中使用模块是否可以解决这个问题。

这是一个简单的例子 的 TestClassA.ts

namespace Test {
    'use strict';

    import TestClassB = Test.TestClassB;

    export class TestClassA {
        private test: TestClassB;
        constructor() {
            this.test = new TestClassB();
        }
    }
}

TestClassB.ts

namespace Test {
    'use strict';

    export class TestClassB {

        private value: string;

        constructor() {
            this.value = 'test';
        }
    }
}

TestClass.spec.ts

'use strict';

describe('test', (): void => {
    it ('should create an object', (): void => {
        let a: Test.TestClassA = new Test.TestClassA();

        expect(a).toBeDefined();
    });
});

在Karma.config文件中将文件指定为

files: [
      'src/**/*.js',
      'test/**/*.spec.js'
    ],

测试将失败,但TestClassB不是构造函数。

如果我将Karma.config文件指定为 文件:[' src / TestClassB.ts',' src / TestClassA.ts',' test / ** / *。spec.ts']

然后测试将通过。

但是对于包含数百个文件的项目来说,这样做是不可维护的。

2 个答案:

答案 0 :(得分:2)

将ES6导入/导出与捆绑器for example with webpack一起使用。

代码

// File TestClassA.ts

import TestClassB from './TestClassB';

export default class TestClassA {
  private test: TestClassB;
  constructor() {
    this.test = new TestClassB();
  }
}

// File TestClassB.ts

export default class TestClassB {
  private value: string;
  constructor() {
    this.value = 'test';
  }
}

配置

// File tsconfig.json

{
  "compilerOptions": {
    // ...
    "module": "commonjs",
    "noEmit": true
  }
  // ...
}

// File webpack.config.js

var path = require("path");

module.exports = {
  entry: path.join(__dirname, "TestClassA.ts"),
  output: {
    path: __dirname,
    filename: "bundle.js"
  },
  resolve: {
    extensions: ["", ".webpack.js", ".web.js", ".ts", ".js"]
  },
  module: {
    loaders: [
      {
        test: /\.ts$/,
        loader: "ts",
        query: {
          "compilerOptions": {
            "noEmit": false
          }
        }
      }
    ]
  }
};

注意:请参阅楼上的链接以了解此配置。

命令

# Install (to run once)
npm install -g webpack typescript
npm install ts-loader typescript

# Make the bundle
webpack

答案 1 :(得分:0)

作为Paleo suggested首选将代码分成多个文件的方法是使用 modules 而不是命名空间。我一直在努力,命名空间确实更适合创建编译的连接输出,但开发人员和大多数社区都忽略了它。

对于非平凡的项目,您基本上强制使用模块,首选语法为ES6 syntax

import { ... } from "./path/to/module-file";

这必须由ES6浏览器,< ES6浏览器(RequireJS)的模块加载系统或NodeJS内置模块加载系统来处理。模块肯定有它们的优点,但它们明显替代名称空间。

然而,我知道有一个理论解决方案:如果你有一个指定的根文件,并且你的命名空间结构反映了目录布局(例如::namespace Test.Helpers在文件夹中test/helpers,请参阅下面的链接问题),可以轻松编写一个工具,以递归方式扫描文件中的import X = ...语句,然后创建一个包含有序列表的_references.ts文件参考路径。 TypeScript编译器应该完成类似的,但事实并非如此。

在visual studio中进行编译时,会自动识别此_references.ts文件并将其传递给编译器,但是AFAIK,您也可以手动将该文件传递给编译器,只需:

tsc _references.ts --out test.js

然后还将编译其中引用的文件。

我在使用这种方法时使用了用C#编写的定制的~200行捆绑程序,然后再切换到ES6模块导入语法。您需要注意一些警告:

    当嵌套多个名称空间时,
  • import X = ...语句可以使用来自任何名称空间的相对路径。您需要强制自己仅使用绝对命名空间名称,或处理所有情况。
  • 必须检查循环依赖关系。
  • 我可能没有遇到过......