【问题标题】:Importing Victor.js in TypeScript?在 TypeScript 中导入 Victor.js?
【发布时间】: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,这给了我:“模块没有默认导出”。

标签: javascript typescript import module


【解决方案1】:

为我解决了导出问题:

export{vector}

【讨论】:

  • 这并不能真正回答问题。如果您有其他问题,可以点击 进行提问。要在此问题有新答案时收到通知,您可以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
    
    1. “工作版”意思是tsc 似乎编译没有抱怨
    2. 在 helloworld.ts import {AthenaExpress} from "athena-express";
    3. 在 helloworld.ts import * as AthenaExpress from "./athena-express";

    【讨论】:

      【解决方案4】:

      简介

      您正在尝试使用victor,就好像它是一个 es6 模块一样,但事实并非如此。我看到两个选项:

      1. tsc 将您的模块转换为commonjs 这样的格式,在这种情况下tsc 将在victor 和您的代码之间提供必要的粘合逻辑

      2. 或者您需要通过提供胶水的模块加载器来加载您的应用程序。

      详细说明

      当我使用您显示的导入运行最新的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 等)。
      • 多么好的解释!美丽
      猜你喜欢
      • 2016-09-06
      • 2021-06-19
      • 1970-01-01
      • 2017-05-31
      • 2018-11-22
      • 2021-05-18
      • 2017-03-27
      • 2018-10-04
      相关资源
      最近更新 更多