Javascript 打字稿2—;使用"ES6 import& ;;要求
我在使用ES6模块的Angular2应用程序中导出了一个Javascript 打字稿2—;使用"ES6 import& ;;要求,javascript,angular,typescript,module,webpack,Javascript,Angular,Typescript,Module,Webpack,我在使用ES6模块的Angular2应用程序中导出了一个类: //File = init.todos.ts export class Init { load() { ... } } 我正在通过以下方式从另一个组件导入此类: //File = todo.service.ts import { Init } from './init.todos' 它按预期工作 但是,如果我将加载机制更改为commonjs: //File = init.todos.ts export
类
:
//File = init.todos.ts
export class Init {
load() {
...
}
}
我正在通过以下方式从另一个组件导入此类:
//File = todo.service.ts
import { Init } from './init.todos'
它按预期工作
但是,如果我将加载机制更改为commonjs:
//File = init.todos.ts
export class Init {
load() {
...
}
}
module.exports.Init = Init;
要求:
//File = todo.service.ts
var Init = require("./init.todos");
-我发现这些错误:
…myApp/src/app/todo.service.ts
(4,13):找不到名称“require”。)
…myApp/src/app/todo.service.ts(12,14):
类型“TodoService”上不存在属性“load”。)
问题:
如何使用require
加载commonjs模块
Tsconfig.json:
{
"compileOnSave": false,
"compilerOptions": {
"outDir": "./dist/out-tsc",
"baseUrl": "src",
"module": "system",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es5",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2016",
"dom"
]
}
}
以下是配置文件:
TypeScript符合ES6标准。在TypeScript源文件中使用ES6模块加载语法:
import { SomeType } from './some.module';
当TypeScript编译为常规JavaScript时,您可以选择一个模块系统作为目标:
"compileOptions": {
"module": "commonjs" (or system, umd, amd)
}
无论选择什么目标模块系统,都需要确保包含加载模块所需的脚本和配置。i、 e.系统、需求等
作为练习,尝试针对不同的模块加载程序,并检查.js文件-您将了解我的意思。因为Typescript采用了ES6风格的导入
您可以保持代码“原样”
通过将tsconfig.json
中的属性module
移动到commonjs
,transpiler将生成与commonjs兼容的javascript,使您能够受益于整个nodeJS生态系统,并为之做出贡献
"compileOptions": {
...
"module": "commonjs"
...
}
如果希望在typescript代码中导入现有的NodeJS模块,可能会发生一些事情
- 该模块附带嵌入式Typescript定义文件(“package.json”中有一个“typings”条目)。在这种情况下,使用ES6语法导入模块就可以了(
)。是这样一个图书馆的好例子import*as blah from'blah'
- 该模块不附带定义文件,但在上有一个可用的定义文件
- 运行
以获取项目中的定义npm install@types/blah
- 并像往常一样导入模块:
import*作为“blah”中的blah
- 运行
- 模块没有定义文件
- 您可以制作一个,只需在命名为
后将其添加到您的项目中即可。这件事肯定是打字的blah.d.ts
- 您可以决定不键入,只需使用NodeJS require()
,而const blah=require('blah')
将具有typeblah
(这实际上意味着any
选择不键入)blah
- 您可以制作一个,只需在命名为
(为了完整起见,我可以添加1.8版以来可用的,但这本身就是一个完整的主题)您问题的问题实际上不是require(…)方法。问题是您引用了error Init。我认为您希望通过require加载模块。但是您加载了包含实例方法的类
load
(它不是类方法,如果需要,必须将其声明为static
)。因此,必须在使用它之前创建实例。默认情况下,require(…)返回任何
declare function require(id: string): any;
如果希望typescript正确推断类型,则必须声明require()返回类型,例如:let foo:typeof foo=require('foo'))
。我发现当模块
不是系统
时,ts jest
测试通过,因为它是延迟加载,不能立即执行测试定义,所以我确定问题不在模块。以下是我的测试代码:
试验
这是因为您有
“module”:“system”
。SystemJS中没有require函数。@estus我已经在tsconfig中了,请将“module”更改为“commonjs”,并保留ES6语法,例如`import{Init}来自“/init.todos”。@BrunoGrieder哦,所以导入的模块将具有模块.exports
,但我仍然应该通过es6语法导入它?是的。Typescript在不久前(1.5或1.7)采用了es6样式导入。如果您使用const x=require('blah')
,您将使用NodeJS/CommonJS require和“lose”因为x
会被映射到任何类型。这对于导入未被键入的JS库可能很有用,虽然我很抱歉,但您的意思是在第二种情况下:“模块没有附带定义文件,但在DefiniteTyped上有一个可用的,很简单”-我可以通过“常规要求”导入它。对吗?(我的意思是肯定我可以通过ES6导入获得它,但关键是d.ts允许ts识别需求,不是吗?)ts不“识别需求”。拥有定义文件的意义在于,JS模块可以像用typescript编写一样使用,因此可以使用typescript导入语法导入,这是ES6导入语法是的,这就是我的意思,它允许TS编译器识别新的d.TS'ed
关键字。(如果我错了,请纠正我)但是我还是想问一下你提到的第二个例子。即使我添加了我朋友用他的blah库(commonjs)发给我的blah.d.ts
,Typescript只会在我的代码中包含关于require('blah')
的静音错误。对吗?我的意思是我必须有另一个模块加载器(browserify/webpack)为了让最终的JS实际引用所需的文件。对吗?是的。你需要一个模块绑定器,如browserify或webpack。使用require
或allowJs
你可能可以避免使用一个,但你失去了打字的好处:-)(最后我开始得到它。)-好的,如果是的话-如果我更改Tconfig中的模块
,会有什么区别?我的意思是-它首先与TS有什么关系?从我的测试中-TS搜索es6语法并转换它..你知道我的误解在哪里吗?TS与Tconfig的模块设置有什么关系?我的意思是它取决于webpack/browserify到“需要”库(es6导入内置INT除外)。
declare function require(id: string): any;
//for inferer type for typescript
//This leverages the reference-elision optimization,
//so that the module is only loaded when needed.
//so use InitClass as a type will skipped.
import {Init as InitClass} from "./init.todos";
test("typescript dynamic load supports inferer types", () => {
let Init: typeof InitClass = require("./init.todos").Init;
let it = new Init();
expect(it.load()).toEqual("bar");
});