【问题标题】:Triple Slash Typescript References with 2.0 Libraries带有 2.0 库的三斜杠打字稿参考
【发布时间】:2017-01-26 22:50:50
【问题描述】:

我有一个最初基于 Typescript 1.4 构建的项目

它有一个像这样的主文件设置:

/// <reference path="typedefinitions/jquery/jquery.d.ts" />
/// <reference path="typedefinitions/jqueryui/jqueryui.d.ts" />
/// <reference path="typedefinitions/moment/moment.d.ts" />
module myApp {
   ...
}

所有其他文件都只是引用这个主文件:

/// <reference path="../mainfile.ts" />
module myApp {
   //more code that can reference anything else in myApp
}

我们构建过程的一部分将我们所有的应用程序打字稿文件连接在一起,因此我们没有使用任何模块加载器。

在过去这很好用,但是,越来越多的库使用import 设置其定义文件,并且使用上述方法引用它们不起作用。

ui-router为例,如果我添加:

/// <reference path="../node_modules/angular-ui-router/lib/index.d.ts"  />

引用的类型似乎没有出现在任何地方。如果我这样做:

import * as router from 'angular-ui-router';

那么所有其他文件都不能再引用“myApp”。

我最好的办法是重构我摆脱这种情况的方法,同时仍然能够将所有 TS 文件编译成单个 javascript 文件?

有我可以更改的 tsconfig 设置吗?或者我还缺少什么?

【问题讨论】:

  • 不幸的是,如果可能的话,我会切换到为您捆绑文件的模块加载器。与 JavaScript 正在成为的东西抗争是不值得的。请记住,一旦 http2 被广泛使用,单个文件包将不是一件好事

标签: typescript typescript2.0


【解决方案1】:

这里有几个选项。

推荐的方法

如今,摩擦最小的选项是包含一个打包器来处理您的单个文件需求,并使用 ES6 样式的模块系统来建立依赖关系(过去称为外部模块)。据我所知,命名空间系统并没有被正式弃用,但在我看来,从社区来看,命名空间系统基本上已经被抛弃了。它与 import 语句和 @types 系统不兼容,您将看到的大多数示例和代码都将使用它们。使用此选项将需要通过每个文件中的导入来建立显式依赖关系,而不是利用 C# 样式命名空间。

然后,您可以使用 systemjs、uglify、browserify 等工具来遍历依赖关系树并创建一个 javascript 包。原则上,有些人更喜欢这纯粹是为了将编译任务与缩小和捆绑分开。这也将解决您在使用纯名称空间时可能遇到的一些乱序问题,因为每个文件(模块)都明确指定了其确切的依赖关系。

其他选项

你可以在短期内通过手动下载 .d.ts 文件来使用命名空间(或者当然使用类型,如果你遵循这条路线,我会推荐它)。几个 npm 包现在在其依赖项中列出了 @types 包,因此您可能需要设置 types: [] 配置属性以确保不使用来自 @types 的任何内容,从而避免冲突。

虽然这仍然是一个可行的选择,但我建议采用 ES6 模块。这不是 typescript 决定的事情,JS 社区正在朝着这个方向发展,作为 JS 的超集,主要的结构性 JS 决策将渗透到 TS 中,这将成为默认值。我觉得命名空间将很快成为遗留代码,有些人认为命名空间已经遗留。

【讨论】:

  • 我的问题是因为没有真正引用我的组件(它们都引用主应用程序以将自己注册为组件,但仅此而已 - 没有任何引用它们),它们永远不会被 SystemJs 加载:我怎么得到周围?我是否需要在某个地方手动引用文件中的每个组件才能让它们注册 angular?
  • @John TBH 我的公司就是这样做的,但我并不对此感到疯狂,因为您必须在两个地方维护更改。就我个人而言,我更喜欢反转它,以便在真空中定义组件并在模块定义中导入和注册。这两个选项都不是很好,后者更接近 angular 2 方法。我想这样做是为了拥有一个合理的依赖树,而无需手动列出所有叶节点,因此它可以很好地与模块配合使用。
  • @John 可能有某种方法可以按照某种模式动态加载所有模块,因此模块加载器将执行该块,即使它从未明确包含在内,但我不确定这是否是一个烘焙功能。您可以通过System.registry keys 自己实现它
  • 感谢您的帮助:我刚刚添加了一个关于我认为我将如何处理这种情况的答案
【解决方案2】:

Paarth,我想我会以与 Angular 2 类似的方式处理该问题,我将在其父组件中注册子组件:

hello.component.ts:

import Component from './component.decorator';

@Component('hello', {
    controllerAs: 'vm',
    template: '<div>Hi</div>'
})
export default class HelloComponent { }

app.component.ts:

import Component from './component.decorator';
import HelloComponent from './hello.component';

@Component('app', {
    controllerAs: 'vm',
    directives: [HelloComponent],
    template: `<div>
                <div>{{vm.Message}}</div>
                <hello></hello>
               </div>`
})
export class AppComponent {
    Message: string;

    $onInit() {
        this.Message = 'Hi!!!';
    }
}

component.decorator.ts:

import * as angular from 'angular';
import app from './main';

export interface ComponentBridgeOptions extends ng.IComponentOptions {
    directives?: any[];
}

export default function Component(selector: string, options: ComponentBridgeOptions) {
    return (controller: Function) => {
        app.component(selector, angular.extend(options, { controller: controller }));
    }
}

【讨论】:

    猜你喜欢
    • 2019-01-15
    • 1970-01-01
    • 2011-09-13
    • 2012-12-09
    • 2016-07-29
    • 1970-01-01
    • 2020-12-19
    • 2015-06-29
    相关资源
    最近更新 更多