【问题标题】:Can't import library the same way in typescript and javascript无法在 typescript 和 javascript 中以相同的方式导入库
【发布时间】:2021-10-28 06:48:47
【问题描述】:

我正在制作自己的库,我想同时使用 javascript 和 typescript。

tsconfig.json

{
    "compilerOptions": {
        "target": "es2017",
        "module": "commonjs",
        "declaration": true,
        "outDir": "./lib",
        "esModuleInterop": true
    },
    "include": [
        "src"
    ],
    "exclude": [
        "node_modules",
        "**/__tests__/*"
    ]
}

package.json

{
    "main": "lib/classA.js",
    "types": "lib/classA.d.ts",
    "files": [
      "lib/**/*"
    ],
    "scripts": {
      "build": "tsc"
    }
  }
/*
.
.
.
*/

classAInterfaces.ts

export interface IClassA<T> {
  size(): number;
  /*
  .
  .
  .
  */
}

classA.ts

import { IClassA } from './classAInterfaces';

export default class ClassA<T> implements IClassA<T> {
  constructor() {
      // ...
  }

  size() {
      // ...
  }
  /*
  .
  .
  .
   */
}

它被编译为:

classA.d.ts

import { IClassA } from './ClassAInterfaces';
export default class ClassA<T> implements IClassA<T> {
    constructor();
    size(): number;
}

classA.js

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class ClassA {
    constructor(options) {
    // ...
    }
    size() {
     // ...
    }
}
exports.default = ClassA;

classAInterfaces.d.ts

export interface IClassA<T> {
    size(): number;
/*
.
.
.
*/
}

classAInterfaces.js

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

现在,当我想在我的项目中使用它时,我在 typescript 项目中使用它没有任何问题(我在 nestjs 中构建这个 ts 项目)

tsconfig.build.json

{
  "extends": "./tsconfig.json",
  "exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
}

tsconfig.json

{
  "compilerOptions": {
    "module": "commonjs",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "target": "es2017",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true,
    "skipLibCheck": true,
    "strictNullChecks": false,
    "noImplicitAny": false,
    "strictBindCallApply": false,
    "forceConsistentCasingInFileNames": false,
    "noFallthroughCasesInSwitch": false
  }
}

package.json

{
    "scripts": {
      "build": "nest build",
      "start": "nest start",
    }
    /*
    .
    .
    .
    */
  }

ma​​in.ts

import ClassA from 'class-a';

async function main() {
  console.log('--------------------------------', ClassA);
  const q = new ClassA<number>();
  console.log('---------', q.size());
}
main();

它按预期工作,打印:

-------------------------------- [class ClassA]
--------- 0

但是,当我尝试在 javascript 项目中使用它时

package.json

{
    "type": "module",
    "main": "index.js",
    "scripts": {
      "start": "node ./index.js"
    }
    /*
    .
    .
    .
    */
  }

index.js

import ClassA from 'class-a'


console.log('--------------------------------', ClassA);
const q = new ClassA();
console.log('---------', q.size());

我得到以下输出:

-------------------------------- { default: [class ClassA] }
file:///C:/Users/win/Desktop/projects/tesst%20library/index.js:5
const q = new ClassA();
          ^

TypeError: ClassA is not a constructor

我可以使用它

const q = new ClassA.default();

但我不喜欢它,我想像在打字稿中一样使用它。

我想出的唯一解决方案是更改 classA.ts 导出:

import { IClassA } from './classAInterfaces';

class ClassA<T> implements IClassA<T> {
  constructor() {
    // ...
  }

  size() {
   // ..
  }
}
export = ClassA;

然后将 classA.js 更改为

"use strict";
class ClassA {
    constructor(options) {
    // ...    
    }
    size() {
    // ...
    }
}
module.exports = ClassA;

classA.d.ts 到:

import { IClassA } from './ClassAInterfaces';
declare class ClassA<T> implements IClassA<T> {
    constructor();
    size(): number;
}
export = ClassA;

将 classA.js 的导出更改为 CommonJS,如导出。该解决方案的问题是我的打字稿项目不再识别我的库(main.ts 打印“-------------- ------ 第一行未定义)

【问题讨论】:

  • 你已经将你的 typescript 转换成一个 commonjs 模块。如果你想在 JS type: module 项目中使用它,你仍然需要 import it like a commonjs module。如果要导入 es 模块,请更改 typescript 编译器设置以输出 es 模块并更改 class-a 包的 package.json 以反映这一点。 Nodejs 不关心 __esModule - 只有编译器(babel、tsc)构建的脚本才关心。

标签: javascript node.js typescript commonjs ecma


【解决方案1】:

通常,您只需将“.js”添加到导入语句的末尾即可:

import * as whatever from 'file.js';

对所有 .ts 导入执行此操作,一切正常。即使扩展名是JS,TS编译器也会把它当成同名的TS文件,到编译的时候,JS会正确导入文件。

【讨论】:

    猜你喜欢
    • 2021-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-22
    • 1970-01-01
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多