TypeScript:如何不使用相对路径导入类?

时间:2016-01-28 18:06:42

标签: typescript angular electron

我目前正在使用TypeScript和Angular2开发一个Electron应用程序,为此我创建了许多不同的类,所有这些都在不同的文件中。为了使我的应用程序的重构更容易,我希望在导入这些类时不必使用相对路径。
现在,要导入它们,我使用以下语法:import {Trigger} from './../../trigger/ts/trigger.component';
我想要做的是使用如下所示的语法:import {Trigger} from 'trigger.component';
那可能吗?

5 个答案:

答案 0 :(得分:3)

您可以创建一个文件,例如:components.ts,并在该组件中引用所有组件,例如:

export {Trigger} from '../trigger/ts/trigger.component'
export {Cmp} from '../cmp/ts/cmp.component'
...

比,当你想加载一个组件时,你可以这样做:

import {Trigger} from '../components.ts'

分组事物是一种很好的做法。

答案 1 :(得分:2)

我使用ScriptCS创建了一个导出器来做到这一点。我是用C#写的,但是欢迎你用你喜欢的任何语言重写它。

Here is an example on GitHub

它允许您在每个组件目录的根目录中有一个导出文件,您可以通过执行以下操作导入该文件:

import {LoginPage, HomePage} from '../pages/export'

import {NavBarComponent, HeroCardComponent} from '../controls/export'

假设您在特定目录中有多个组件,例如:

  • 应用程序/网页/登录页/登录-page.ts
  • 应用程序/页/家庭页/家庭page.ts
  • 应用程序/控制/ NAV-bar.ts
  • 应用程序/控制/英雄card.ts

如果您运行scriptcs exporter.cs -- app/pages app/controls

它将在每个指定的目录中生成一个名为export.ts的输出文件,其中包含目录中包含的每个类的导出语句(通过递归迭代)

<强> exporter.cs

// USAGE
// scriptcs exporter.cs -- app/Templates app/Controls

using System.Text.RegularExpressions;

CreateExports();

public void CreateExports() {
    // e.g. 'C:\Apps\MyProject'
    string rootDir = new DirectoryInfo(@".\").FullName;

    string exportFileName = "export.ts";
    List<string> exportDirectoryPaths = new List<string>();
    foreach (string argument in Env.ScriptArgs) {
        if (argument.Contains(".ts"))
            exportFileName = argument;
        else
            exportDirectoryPaths.Add(argument);
    }
    Console.WriteLine("File Name:" + exportFileName);
    foreach (string exportDirPath in exportDirectoryPaths) {
        // e.g. 'app\Templates'
        var exportDirPathFixed = exportDirPath.Replace("/", "\\");
        Console.WriteLine(String.Format("Exporting -> {0}", exportDirPath));

        List<ExportEntry> exportEntriesToWrite = new List<ExportEntry>();
        // e.g. 'C:\Apps\MyProject\app\Templates' 
        DirectoryInfo exportDir = new DirectoryInfo(rootDir + exportDirPathFixed);
        foreach (FileInfo file in exportDir.EnumerateFiles("*.ts", SearchOption.AllDirectories)) {
            // Don't export the export file ;)
            if (file.Name == exportFileName)
                continue;
            // e.g. toAdd = {
                // RelativepathToExportDirectory = './app/templates/template-one.component'
                // ClassName = 'TemplateOneComponent' (Parsed from file contents, works with interfaces)
            ExportEntry toAdd = CreateExportEntry(file, exportDirPathFixed, rootDir);
            exportEntriesToWrite.Add(toAdd);
        }
        CreateExportFile(exportDir.FullName + "\\" + exportFileName, exportEntriesToWrite);

    }
}


private void CreateExportFile(string exportFilePath, IEnumerable<ExportEntry> exportEntries) {
    string textToWrite = "";
    foreach (ExportEntry entry in exportEntries) {
        textToWrite += entry.ToString() + Environment.NewLine;
    }
    Console.WriteLine("Text: " + Environment.NewLine + textToWrite);
    File.WriteAllText(exportFilePath, textToWrite);
}

// -- Create Export Entry -- //
private ExportEntry CreateExportEntry(FileInfo exportFile, string exportDirPath, string rootDir) {
    ExportEntry toReturn = new ExportEntry() {
        ClassName = GetFirstExportClassName(exportFile),
        RelativepathToExportDirectory = exportFile.FullName.Remove(0, rootDir.Length + exportDirPath.Length).Replace(".ts", ""),
    };
    return toReturn;

}
private string GetFirstExportClassName(FileInfo exportFile) {
    string className = null;
    Regex regular = new Regex(@"(?<=export[\s+]class|interface)[^s+][^\s]+");

    using (StreamReader streamer = new StreamReader(exportFile.OpenRead())) {
        string contents = streamer.ReadToEnd();
        Match componentNameMatch = regular.Match(contents);
        className = componentNameMatch.ToString().Replace("{", "");
    }
    return className;
}

public class ExportEntry {
    public string RelativepathToExportDirectory { get; set; }
    private string _ClassName;
    public string ClassName { 
        get { return _ClassName; }
        set { _ClassName = value.Trim(); }
    }

    /// <summary>
    /// Returns the formatted export entry 
    /// e.g. " export {MyComponents} from './Components/my-component.component' "
    /// </summary>
    /// <returns></returns>
    public override string ToString() {
        //      export { AppComponent} from './my-template/my-template.component'
        return String.Format("export {{ {0} }} from '.{1}';", this.ClassName, this.RelativepathToExportDirectory).Replace('\\', '/');
    }
}

答案 2 :(得分:2)

最好在tsconfig.json中使用以下配置

{
  "compilerOptions": {
    "...": "reduced for brevity",

    "baseUrl": "src",
    "paths": {
      "@app/*": ["app/*"],
      "@trigger/*": ["app/trigger/ts/*"]
    }
  }
}

对于您的情况,使用可以import {Trigger} from '@app/trigger/ts/trigger.component';import {Trigger} from '@trigger/trigger.component';或您可以配置的任何级别的路径。

答案 3 :(得分:0)

实现这一目标的一种简单方法是使用Typescript v2。*的路径,就像在这里使用它一样:https://github.com/MarkPieszak/aspnetcore-angular2-universal

总之,您可以将index.ts文件添加到文件夹,例如

   export * from './app.component'
   export * from './shared/other.component'

然后让webpack来处理它。 您应该添加到webpack.config.js

    const clone = require('js.clone');
    const ContextReplacementPlugin = require('webpack/lib/ContextReplacementPlugin');
    const TsConfigPathsPlugin = require('awesome-typescript-loader').TsConfigPathsPlugin;
    [...]
    const config = setTypeScriptAlias(require('./tsconfig.json'), {
      [...]
      plugins: [
        new ContextReplacementPlugin(
            // The (\\|\/) piece accounts for path separators in *nix and Windows
            /angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
            root('./ClientApp')
        ),

        new TsConfigPathsPlugin({
            tsconfig: 'tsconfig.json'
        }), [...]

使用这些帮助功能:

function setTypeScriptAlias(tsConfig, config) {
  var newConfig = clone(config);
  newConfig = newConfig || {};
  newConfig.resolve = newConfig.resolve || {};
  newConfig.resolve.alias = newConfig.resolve.alias || {};
  var tsPaths = tsConfig.compilerOptions.paths;
  for (var prop in tsPaths) {
    newConfig.resolve.alias[prop] = root(tsPaths[prop][0]);
  }
  return newConfig;
}

function root(args) {
  args = Array.prototype.slice.call(arguments, 0);
  return path.join.apply(path, [__dirname].concat(args));
}

最后在tsconfig.js中定义路径

 "compilerOptions": {
    [...]
    "paths": {
        "app":  [ "./ClientApp/app" ] 
    },[...]

然后你可以通过&#34; app&#34;路径如

   import { AppModule } from 'app';

答案 4 :(得分:0)

我可以通过将以下内容添加到tsconfig.app.json中来使其工作:

"compilerOptions": {
  "baseUrl": "./",
  ...
}

,如https://www.typescriptlang.org/v2/en/tsconfig#moduleResolution中所述。它已经在tsconfig.json中,但显然仅用于IDE integration