[英]General TypeScript usage for modules / namespaces
我有一个使用jQuery和其他库的标准网页(不是使用angular,react,vue等渲染的应用程序)。
我想将良好实践与TypeScript集成在一起。 做这个的最好方式是什么?
我当前的想法是拥有3个文件:
我目前有这些内容:
索引
// Type definitions for test 1.0.0
// Project: Test
// Definitions by: Author Name
/// <reference path="../../lib/@types/jquery/index.d.ts" />
declare namespace TestNS {
export class TestClass {
// Fields
element: JQuery;
value: string;
constructor(element: JQuery, val: string);
OnCreate();
static AttachToJQuery(jq: JQueryStatic): void;
}
interface JQuery {
TestClass(element: JQuery, val?: string): TestNS.TestClass;
}
interface JQueryStatic {
TestClass(element: JQuery, val?: string): TestNS.TestClass;
}
}
Test.ts (在jQuery之后加载第2个)
/// <reference path="../../lib/@types/jquery/index.d.ts" />
/// <reference path="./index.d.ts" />
export namespace TestNS {
export class TestClass {
// Fields
element: JQuery;
value: string;
constructor(element: JQuery, val: string) {
this.element = element;
this.value = val;
this.OnCreate();
}
OnCreate() {
this.element.data('test-value', this.value);
}
static AttachToJQuery(jq: JQueryStatic) {
//no jQuery around
if (!jq) {
return false;
}
jq.fn.extend({
TestNS: function(newVal) {
return this.each(function() {
var obj = jq(this);
new TestNS.TestClass(obj, newVal);
});
}
});
}//attach to jquery method (to easily work with noconflict mode)
}//test class
}
page.js (最后加载)
let newJquery:JQueryStatic = jQuery.noConflict();
TestNS.TestClass.AttachToJQuery(newJquery);
let testElems = newJquery(".testClass");
testElems.TestClass();
我的目标是将我的代码整齐地组织在打字稿中以及在页面上的命名空间中(但在打字稿中这样做会产生与重复标识符有关的错误),并且具有模块化和可扩展性。 我知道我应该将我的类型发布在“ node_modules / @ types”目录下,但是我现在只是希望它们都封装在此模块中。
我尝试使用模块,并导入index.d.ts中定义的内容,但是TypeScript说我无法导入此文件,并且找不到模块名称。 我确实了解到,如果使用模块,则应将其与诸如CommonJS,RequireJS或AMD的加载器一起使用,但是我现在最好避免这样做(如果这样做不是很糟糕的做法,我想暂时将复杂程度降至最低)。
我尝试查看其他项目,但它们都使用加载程序,对于这种脚本来说似乎有点过分了。
有没有解决这个问题的好方法?
如果您想在没有模块加载器的情况下工作,则必须进行一些更改。 首先,值得一提的是TypeScript支持两种主要的模块化代码,名称空间和模块的方式。
注意:这里有一个令人困惑的细微差别是,关键字namespace
和module
可以互换使用,而不能自行确定事物是模块还是命名空间。
1)模块(以前称为外部模块)-这些模块使用典型的导入,导出,并且需要语义,并且需要模块加载器,最好是某种捆绑器。 对于此模式,每个文件都被视为一个模块。 包含任何导入或导出语句的任何文件都将被TypeScript编译器视为外部模块。
2)名称空间(以前称为内部模块)-此模式支持可以跨越多个文件的名称空间。 如果您不想使用模块加载器,则这是您需要使用的模块类型。 这种模式的使用变得不那么普遍了,但是如果您出于任何原因想要使用它,它仍然是一个选择。 要使用这种类型的模块化,文件中不能包含任何导入或导出语句。
这是有关namespaces
的文档https://www.typescriptlang.org/docs/handbook/namespaces.html
假设您想使用原始计划,则需要在代码中进行一些调整。
1)如@sbat所述,您的index.d.ts
正在重新声明您的名称空间和类类型。 这可能会导致重复的定义错误。 您可以使用JQuery接口的简单覆盖替换全部内容。
/** Extend the JQuery interface with custom method. */
declare interface JQuery {
TestNS: () => TestNS.TestClass
}
2)确保您没有任何顶级出口或进口。 具体来说,您将要从test.ts
的名称空间中删除export
。 这将使您的模块成为internal
模块,而不是external
模块。
namespace TestNS {
export class TestClass {
...
}
}
假设您只想在一个简单的项目中尝试TypeScript,建议您简化一下操作:
删除index.d.ts。 定义文件描述了现有的javascript代码,因此TypeScript可以识别其中的类型。 您的项目中没有这种情况,不需要重复test.ts中已有的类型信息,可以安全地删除此文件。
只需将您的test.ts构建到test.js中即可。 确保您的jquery .d.ts位于应有的位置。
删除page.js,只需在test.ts中编写所有代码即可进行测试。 一旦使它起作用,就可以对其进行重组。
但是,如果您的目标是使代码模块化和可扩展,则建议的方法是确实使用模块:
从ECMAScript 2015开始,模块是语言的本机部分,并且所有兼容引擎实现均应支持该模块。 因此,对于新项目,模块将是推荐的代码组织机制。
https://www.typescriptlang.org/docs/handbook/namespaces-and-modules.html
要在浏览器的生产环境中使用模块,您将需要:
捆绑器。 该工具将调用TypeScript来构建您的单个TS模块,然后将构建输出组合到单个javascript文件中。 然后,您将把这个文件包含到HTML中。 WebPack可能是最容易启动的: https : //webpack.js.org/concepts/
包管理器。 安装和管理第三方模块版本的工具。 https://www.npmjs.com/
这是一个需要研究的大领域,但我认为这不是一个过大的选择。 如果您的代码是模块化的(即使只是2个模块),则需要一种基础结构来以一种方式捆绑和加载模块。 有几种具有不同利益和取舍的选择,但是从根本上来说,这是没有办法的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.