Javascript 在 TypeScript 中导入 Victor.js?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/54701255/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Importing Victor.js in TypeScript?
提问by radman
I'm trying to use the victor.jslibrary in a TypeScript project (3.0.1) and I'm having real heartache trying to import and use it. I've installed it from npm along with it's typings (victor @types/victor). I've tried to import it a myriad of ways but can't seem to get it to import along with type resolution in my IDE.
我正在尝试在 TypeScript 项目 (3.0.1) 中使用victor.js库,但在尝试导入和使用它时我真的很心痛。我已经从 npm 安装了它以及它的类型(victor @types/victor)。我已经尝试通过多种方式导入它,但似乎无法在我的 IDE 中将它与类型解析一起导入。
I've tried these:
我试过这些:
import { Victor} from 'victor';
import * as v from 'victor';
(This module can only be referenced with ECMAScript imports/exports by turning on the 'allowSyntheticDefaultImports' flag and referencing its default export)
(此模块只能通过打开 'allowSyntheticDefaultImports' 标志并引用其默认导出来引用 ECMAScript 导入/导出)
import Victor = require('victor');
(works but not compatible when targeting ecmascript modules)
(在定位 ecmascript 模块时有效但不兼容)
const Victor = require("victor");
(Imports validly and I can construct objects but none of the typings are present)
(有效导入,我可以构造对象,但不存在任何类型)
I'm sure someone out there has run into a similar situation to this before. If it helps the top of the index.js of victor has the line:
我敢肯定,之前有人遇到过与此类似的情况。如果它有助于 victor 的 index.js 顶部有一行:
exports = module.exports = Victor;
回答by Louis
In Brief
简单来说
You're trying to use victoras if it were an es6 module, but it is not. I see two options:
您试图将其victor用作 es6 模块,但事实并非如此。我看到两个选项:
Let
tscconvert your modules to a format likecommonjs, in which casetscwill provide necessary glue logic betweenvictorand your codeOr you need to load your application through a module loader that provides the glue.
让
tsc您的模块转换为类似 的格式commonjs,在这种情况下,tsc将在victor您的代码之间提供必要的粘合逻辑或者您需要通过提供胶水的模块加载器加载您的应用程序。
Detailed Explanation
详细说明
When I run the latest tscwith the import that you show, the error I get is:
当我tsc使用您显示的导入运行最新版本时,我得到的错误是:
This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export.
此模块只能通过打开“esModuleInterop”标志并引用其默认导出来使用 ECMAScript 导入/导出来引用。
When I turn on esModuleInterop, then it works just fine. Here is the test code I've used:
当我打开时esModuleInterop,它工作得很好。这是我使用的测试代码:
import Victor from "victor";
const foo = new Victor(1, 2);
console.log(foo.y);
And the tsconfig.json:
和tsconfig.json:
{
"compilerOptions": {
"esModuleInterop": true
}
}
The issue originates due to the fact that when you do import Victor from "victor"you are asking for the value that would be exported through an export default...statement, which is a syntax provided by es6 modules. However, victordoes export anything that corresponds to export default.... So something has to bridge the gap. With what I've shown above, when you compile, tscemits this:
该问题源于这样一个事实:当您这样做时,import Victor from "victor"您要求通过export default...语句导出的值,这是 es6 模块提供的语法。但是,victor确实会导出与export default.... 所以必须有一些东西来弥合差距。根据我上面显示的内容,当您编译时,tsc会发出以下信息:
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
exports.__esModule = true;
var victor_1 = __importDefault(require("victor"));
var foo = new victor_1["default"](1, 2);
console.log(foo.y);
Note the __importDefaulthelper function. It is used whenever the TS code wants to access what a module exports as export default...What it does is check whether the module claims to be an es6 module. An es6 module that wants to export a default value is already correctly structured so there's nothing to do if the module is an es6 module. If the module is not an es6 module, then the helper creates a kind of fake module whose default exported value is the value of the original module.
注意__importDefault辅助函数。每当 TS 代码想要访问模块导出的内容时使用export default...它,它的作用是检查模块是否声称是 es6 模块。想要导出默认值的 es6 模块已经正确构造,因此如果该模块是 es6 模块,则无需执行任何操作。如果模块不是 es6 模块,则帮助程序创建一种假模块,其默认导出值是原始模块的值。
There's an important caveat since you mention "targeting ecmascript modules". If you use, this tsconfig.json:
有一个重要的警告,因为您提到了“针对 ecmascript 模块”。如果你使用,这个tsconfig.json:
{
"compilerOptions": {
"esModuleInterop": true,
"module": "es6"
}
}
Then the emitted code is:
然后发出的代码是:
import Victor from "victor";
var foo = new Victor(1, 2);
console.log(foo.y);
Note that there is no longer any helper function. It is up to the module loader which will load the modules for your application to provide the same logic as provided by __importDefault. If I rename the file to have the mjsextension and run:
请注意,不再有任何辅助函数。由模块加载器为您的应用程序加载模块以提供与__importDefault. 如果我将文件重命名为具有mjs扩展名并运行:
$ node --experimental-modules test.mjs
I get this output:
我得到这个输出:
(node:18394) ExperimentalWarning: The ESM module loader is experimental.
2
When using Node with the experimental module support, it provides the same functionality as __importDefault.
使用带有实验性模块支持的 Node 时,它提供与__importDefault.
When you just use allowSyntheticDefaultImportswithout using esModuleInteropyou are telling the compiler to assumethat there will be something in your toolchain that will do the work of __importDefault. So the compiler does not provide a helper. It allows the compilation to proceed, but youare responsible later to use a module loader that will perform the same work as __importDefault.
当您只使用allowSyntheticDefaultImports而不使用时,esModuleInterop您是在告诉编译器假设您的工具链中会有一些东西可以完成__importDefault. 所以编译器不提供帮助程序。它允许编译继续进行,但您稍后负责使用将执行与__importDefault.
回答by jmunsch
I feel your heartache, In that I spent a large amount of time debugging various errors on how to write typescript definition files for existing javascript modulesand finally got to what I thought was the final hurdle when I got stuck on the same error:
我感到你的心痛,因为我花了大量时间调试关于如何为现有的 javascript 模块编写 typescript 定义文件的各种错误,当我陷入同样的错误时,终于达到了我认为的最后一个障碍:
This module can only be referenced with ECMAScript imports/exports by turning on the 'allowSyntheticDefaultImports' flag and referencing its default export
该模块只能通过打开 'allowSyntheticDefaultImports' 标志并引用其默认导出来引用 ECMAScript 导入/导出
The javascript in question here:
这里有问题的javascript :
module.exports = class AthenaExpress { ...more code.. }
tsconfig.jsonfor the compiling/"Working version" 1:
tsconfig.json对于编译/“工作版本” 1:
{
"compilerOptions": {
"outDir": "dist/",
"sourceMap": true,
"noImplicitAny": true,
"module": "commonjs",
"target": "es6",
"jsx": "react"
},
"baseUrl": "./src",
"include": [
"**/*"
],
"exclude": [
"node_modules"
]
}
"Working version" of the d.tsfile with some import differences 2:
文件的“工作版本”d.ts有一些导入差异2:
declare module 'athena-express' {
import * as aws from "aws-sdk";
interface ConnectionConfigInterface {
aws: typeof aws,
s3: string,
getStats: boolean
}
interface QueryResultsInterface {
Items: any[],
DataScannedInMB: number,
QueryCostInUSD: number,
EngineExecutionTimeInMillis: number,
Count: number,
}
interface QueryInterface {
sql: string,
db: string,
}
type QueryResult = QueryResultsInterface
interface AthenaExpressInterface {
new: (config: ConnectionConfigInterface) => any,
query: (query: QueryInterface) => QueryResult,
}
class AthenaExpress {
new: (config: ConnectionConfigInterface) => any;
constructor(config: ConnectionConfigInterface);
query: (query: QueryInterface) => QueryResult;
}
}
Version of the d.tsfile that received the same error, even when esModuleInteropwas enabled, I also fiddled around with moduleand targetto no avail. With import statement differences 3:
该版本d.ts收到了同样的错误,即使文件esModuleInterop被启用,我也摆弄周围module和target无济于事。与 import 语句差异3:
import * as aws from "aws-sdk";
interface ConnectionConfigInterface {
aws: typeof aws,
s3: string,
getStats: boolean
}
interface QueryResultsInterface {
Items: any[],
DataScannedInMB: number,
QueryCostInUSD: number,
EngineExecutionTimeInMillis: number,
Count: number,
}
interface QueryInterface {
sql: string,
db: string,
}
type QueryResult = QueryResultsInterface
interface AthenaExpressInterface {
new: (config: ConnectionConfigInterface) => any,
query: (query: QueryInterface) => QueryResult,
}
declare class AthenaExpress {
new: (config: ConnectionConfigInterface) => any;
constructor(config: ConnectionConfigInterface);
query: (query: QueryInterface) => QueryResult;
}
export = AthenaExpress
notes:
笔记:
The definition file location and the file I was trying to get working with the definition:
定义文件位置和我试图使用定义的文件:
tree src/backend/js
src/backend/js
├── athena-express.d.ts
└── helloworld.ts
- "Working Version" meaning
tscseemed to compile without complaint - In helloworld.ts
import {AthenaExpress} from "athena-express"; - In helloworld.ts
import * as AthenaExpress from "./athena-express";
- “工作版”的意思
tsc似乎毫无怨言地编译 - 在 helloworld.ts 中
import {AthenaExpress} from "athena-express"; - 在 helloworld.ts 中
import * as AthenaExpress from "./athena-express";
回答by Zpeed Tube
I see there has already been excellent answers but would like to add this shorter answer.
我看到已经有很好的答案,但想添加这个较短的答案。
Error message: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export.ts(2497)
错误信息: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export.ts(2497)
I had this problem with importing when moving from es5 to es6 (and javascript to typescript) when converting my own javascript file to typescript.
将我自己的 javascript 文件转换为 typescript 时,我在从 es5 移动到 es6(以及 javascript 到 typescript)时遇到了导入问题。
Importing like import * as File from "./MyFile"in OtherFile.ts .
像import * as File from "./MyFile"在 OtherFile.ts 中一样导入。
In MyFile.ts file I had export = {funcName}at the end.
在我最后拥有的 MyFile.ts 文件中export = {funcName}。
The solution was to remove =like this export {funcName}from the MyFile.ts file.
解决方案是从 MyFile.ts 文件中删除=这样export {funcName}的内容。
(Hope this helps someone, first time trying to make an answer for a an error/problem)
(希望这对某人有所帮助,第一次尝试回答错误/问题)

