在 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,我也摆弄moduletarget 无济于事。与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?

在普通 TypeScript 文件中导入 Vue 组件失败

如何在 TypeScript 中导入 KnockOut 4?

无法在 TypeScript 中导入 Google Storage