在 TypeScript 中导入 Victor.js?
Posted
技术标签:
【中文标题】在 TypeScript 中导入 Victor.js?【英文标题】:Importing Victor.js in TypeScript? 【发布时间】:2019-07-09 02:53:28 【问题描述】:我正在尝试在 TypeScript 项目 (3.0.1) 中使用 victor.js 库,但我在尝试导入和使用它时感到非常心痛。我已经从 npm 安装了它以及它的类型(victor @types/victor)。我尝试过多种方式导入它,但似乎无法在我的 IDE 中将其与类型解析一起导入。
我试过这些:
import Victor from 'victor';
import * as v from 'victor';
(此模块只能通过打开 'allowSyntheticDefaultImports' 标志并引用其默认导出来引用 ECMAScript 导入/导出)
import Victor = require('victor');
(在针对 ecmascript 模块时有效但不兼容)
const Victor = require("victor");
(有效导入,我可以构造对象,但不存在任何类型)
我敢肯定,以前有人遇到过与此类似的情况。如果对 victor 的 index.js 顶部有帮助的话:
exports = module.exports = Victor;
【问题讨论】:
你试过import Victor from 'victor';
吗?
@MTCoster,这给了我:“模块没有默认导出”。
【参考方案1】:
为我解决了导出问题:
exportvector
【讨论】:
这并不能真正回答问题。如果您有其他问题,可以点击 进行提问。要在此问题有新答案时收到通知,您可以follow this question。一旦你有足够的reputation,你也可以add a bounty 来引起对这个问题的更多关注。 - From Review【参考方案2】:我看到已经有很好的答案,但想添加这个更简短的答案。
错误信息:This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export.ts(2497)
在将我自己的 javascript 文件转换为 typescript 时,从 es5 迁移到 es6(以及 javascript 到 typescript)时,我遇到了导入问题。
在 OtherFile.ts 中像 import * as File from "./MyFile"
一样导入。
在 MyFile.ts 文件中,我最后有 export = funcName
。
解决方案是从 MyFile.ts 文件中删除 =
这样的 export funcName
。
(希望这对第一次尝试为错误/问题做出答案的人有所帮助)
【讨论】:
【参考方案3】:我感到你的心痛,因为我花了大量时间调试 如何为现有 javascript 模块编写 typescript 定义文件上的各种错误,最终达到了我认为的最后一个障碍,当我遇到了同样的错误:
这个模块只能被 ECMAScript 导入/导出引用 打开“allowSyntheticDefaultImports”标志并引用其 默认导出
有问题的 javascript here:
module.exports = class AthenaExpress ...more code..
tsconfig.json
用于编译/“工作版本”1:
"compilerOptions":
"outDir": "dist/",
"sourceMap": true,
"noImplicitAny": true,
"module": "commonjs",
"target": "es6",
"jsx": "react"
,
"baseUrl": "./src",
"include": [
"**/*"
],
"exclude": [
"node_modules"
]
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;
收到相同错误的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
注意事项:
定义文件位置和我试图使用该定义的文件:
tree src/backend/js
src/backend/js
├── athena-express.d.ts
└── helloworld.ts
-
“工作版”意思是
tsc
似乎编译没有抱怨
在 helloworld.ts import AthenaExpress from "athena-express";
在 helloworld.ts import * as AthenaExpress from "./athena-express";
【讨论】:
【参考方案4】:简介
您正在尝试使用victor
,就好像它是一个 es6 模块一样,但事实并非如此。我看到两个选项:
让tsc
将您的模块转换为commonjs
这样的格式,在这种情况下tsc
将在victor
和您的代码之间提供必要的粘合逻辑
或者您需要通过提供胶水的模块加载器来加载您的应用程序。
详细说明
当我使用您显示的导入运行最新的tsc
时,我得到的错误是:
此模块只能通过打开“esModuleInterop”标志并引用其默认导出来通过 ECMAScript 导入/导出引用。
当我打开esModuleInterop
时,它工作得很好。这是我用过的测试代码:
import Victor from "victor";
const foo = new Victor(1, 2);
console.log(foo.y);
还有tsconfig.json
:
"compilerOptions":
"esModuleInterop": true
问题源于这样一个事实:当您执行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);
注意__importDefault
辅助函数。每当 TS 代码想要访问模块导出为 export default...
的内容时使用它,它的作用是检查模块是否声称是 es6 模块。想要导出默认值的 es6 模块的结构已经正确,因此如果该模块是 es6 模块,则无需执行任何操作。如果模块不是 es6 模块,则帮助器创建一种假模块,其默认导出值为原始模块的值。
自从您提到“以 ecmascript 模块为目标”以来,有一个重要的警告。如果你使用,这个tsconfig.json
:
"compilerOptions":
"esModuleInterop": true,
"module": "es6"
那么发出的代码是:
import Victor from "victor";
var foo = new Victor(1, 2);
console.log(foo.y);
请注意,不再有任何辅助函数。这取决于模块加载器,它将为您的应用程序加载模块以提供与__importDefault
提供的相同逻辑。如果我将文件重命名为具有mjs
扩展名并运行:
$ node --experimental-modules test.mjs
我得到这个输出:
(node:18394) ExperimentalWarning: The ESM module loader is experimental.
2
当使用带有实验模块支持的 Node 时,它提供与 __importDefault
相同的功能。
当你只使用allowSyntheticDefaultImports
而不使用esModuleInterop
时,你是在告诉编译器假设你的工具链中会有一些东西可以完成__importDefault
的工作。所以编译器不提供帮助器。它允许编译继续进行,但您稍后负责使用与__importDefault
执行相同工作的模块加载器。
【讨论】:
感谢您的全面回答!尽管哈哈,这两种解决方案的选择都是最低限度的可口。最后一个问题,你知道 Victor.js 使用什么模块格式来触发这种情况吗?可能没有默认导出的 Commonjs? 我的荣幸。是的,它是普通的 CommonJS。 CommonJS 不像 es6 模块那样区分“默认”导出。而且 Victor.js 的作者没有编写使 Victor.js 看起来像 es6 模块所需的胶水(将__esModule
设置为 true
等)。
多么好的解释!美丽以上是关于在 TypeScript 中导入 Victor.js?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 JavaScript 和 TypeScript 中导入/导出?
如何在 TypeScript 中导入 package.json?
如何使用对象解构在 TypeScript 中导入 JSON?