带有 2.0 库的三斜杠 Typescript 参考
Triple Slash Typescript References with 2.0 Libraries
我有一个最初基于 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 设置吗?或者我还缺少其他东西?
这里有几个选项。
推荐的方法
如今,阻力最小的选项是包括一个捆绑器来处理您的单个文件需求,并使用 ES6 风格的模块系统来建立依赖关系(过去称为外部模块)。据我所知,命名空间系统并没有被正式弃用,但在我看来,从社区来看,命名空间系统基本上已经被废弃了。它与 import 语句和 @types 系统不兼容,您将看到的大多数示例和代码都将使用这些系统。执行此选项将需要通过在每个文件中导入来建立显式依赖关系,而不是利用 C# 样式的命名空间。
然后您可以使用 systemjs、uglify、browserify 等工具遍历依赖关系树并创建 javascript 包。原则上,有些人更喜欢这纯粹是为了将编译任务与缩小和捆绑分开。这也将解决您在使用纯命名空间时可能遇到的一些乱序问题,因为每个文件(模块)都明确指定了其确切的依赖项。
其他选项
您可以在短期内通过从 DefinitelyTyped 存储库手动下载 .d.ts 文件(当然也可以使用类型,如果您遵循此路线,我建议您这样做)来凑合使用命名空间。几个 npm 包现在在它们的依赖项中列出了 @types 包,因此您可能需要设置 types: []
配置 属性 以确保不使用 @types 中的任何内容,从而避免冲突。
虽然这仍然是一个可行的选择,但我建议采用 ES6 模块。这不是 typescript 可以决定的问题,JS 社区非常清楚地朝着这个方向发展,作为 JS 的超集,主要的结构 JS 决策将渗透到 TS,这将成为默认。我觉得命名空间将很快成为遗留代码,有些人认为命名空间已经成为遗留代码。
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 }));
}
}
我有一个最初基于 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 设置吗?或者我还缺少其他东西?
这里有几个选项。
推荐的方法
如今,阻力最小的选项是包括一个捆绑器来处理您的单个文件需求,并使用 ES6 风格的模块系统来建立依赖关系(过去称为外部模块)。据我所知,命名空间系统并没有被正式弃用,但在我看来,从社区来看,命名空间系统基本上已经被废弃了。它与 import 语句和 @types 系统不兼容,您将看到的大多数示例和代码都将使用这些系统。执行此选项将需要通过在每个文件中导入来建立显式依赖关系,而不是利用 C# 样式的命名空间。
然后您可以使用 systemjs、uglify、browserify 等工具遍历依赖关系树并创建 javascript 包。原则上,有些人更喜欢这纯粹是为了将编译任务与缩小和捆绑分开。这也将解决您在使用纯命名空间时可能遇到的一些乱序问题,因为每个文件(模块)都明确指定了其确切的依赖项。
其他选项
您可以在短期内通过从 DefinitelyTyped 存储库手动下载 .d.ts 文件(当然也可以使用类型,如果您遵循此路线,我建议您这样做)来凑合使用命名空间。几个 npm 包现在在它们的依赖项中列出了 @types 包,因此您可能需要设置 types: []
配置 属性 以确保不使用 @types 中的任何内容,从而避免冲突。
虽然这仍然是一个可行的选择,但我建议采用 ES6 模块。这不是 typescript 可以决定的问题,JS 社区非常清楚地朝着这个方向发展,作为 JS 的超集,主要的结构 JS 决策将渗透到 TS,这将成为默认。我觉得命名空间将很快成为遗留代码,有些人认为命名空间已经成为遗留代码。
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 }));
}
}