【问题标题】:How to import CommonJS library into a ES Module project without breaking typescript?如何在不破坏打字稿的情况下将 CommonJS 库导入 ES 模块项目?
【发布时间】:2021-06-11 09:14:47
【问题描述】:

我想用 Typescript 编写一个项目。该项目建立在 Typescript 编译器之上,所以我也使用typescript as a library,它(AFAIK)是一个 CommonJS 库。虽然该项目旨在在 Node 上运行(而不是在浏览器中),但我想构建这个项目以尽可能多地使用 ES 模块。也就是说,我在package.json中设置了"type": "module"

示例项目

我在这里创建了一个可重复性最低的示例:https://github.com/evertheylen/test-typescript-import。您可以使用tsc && node build/test-typescript-compile-[...].js 运行文件。有两种方法:

1。标准打字稿导入

查看文件test-typescript-compile-with-import.ts

import * as ts from "typescript";
// This will print: `The ts object has keys: ['default']`
console.log("The ts object has keys:", Object.keys(ts));
// This will of course fail
console.log(ts.createProgram(['foobar.ts'], {noEmitOnError: true}).emit());

在这里,Typescript 静态编译检查工作(即ts.createProgram 被识别为正确的类型)。但是,在运行时,ts 对象只有一个 default 键(即,为了实际运行 createProgram,我必须编写 ts.default.createProgram,而 Typescript 不允许这样做)。

2。使用require

见文件test-typescript-compile-with-require.ts(另见the createRequire docs):

import { createRequire } from 'module';
const require = createRequire(import.meta.url);

const ts = require("typescript");
// This will print: `The ts object has keys: <lots of them>`
console.log("The ts object has keys:", Object.keys(ts));
// This will succeed!
console.log(ts.createProgram(['foobar.ts'], {noEmitOnError: true}).emit());
// The problem is that the 'ts' object is of type any, so (for example)
// the following typo won't be caught at compile time:
console.log(ts.createProogram(['foobar.ts'], {noEmitOnError: true}).emit());

这可行,但 Typescript 无法识别它,并且 ts 对象的类型为 any,这不是我想要的(从示例中可以清楚地看出)。

可能的解决方案

  • Typescript 暂时不会作为 ES 模块使用,请参阅 this issue
  • 使用方法 (1),但以某种方式设置 ts = ts.default(可能使用 @ts-ignore)。我无法让它工作,Node 会抱怨这个。像导入 ES 模块一样导入 CommonJS 库也感觉很 hacky。
  • 使用方法 (2) 但不知何故让 Typescript 相信这个 ts 对象遵循与我导入 typescript 相同的类型。我阅读了declare.d.ts 文件的各种用法,但什么也想不出来。

【问题讨论】:

    标签: node.js typescript es6-modules commonjs


    【解决方案1】:

    我现在觉得有点傻,我搜索了“createRequire typescript”,在ts-node项目中遇到了这个commit:https://github.com/TypeStrong/ts-node/commit/a7aa0af9aefae1a7d801bbfe969148866c852a5c。它显示了在使用require时使用typeof

    我的解决方案归结为:

    import { createRequire } from 'module';
    const require = createRequire(import.meta.url);
    
    import * as _ts from "typescript";
    const ts: typeof _ts = require("typescript");
    

    编辑:虽然这确实解决了诸如createProogram 之类的拼写错误的类型检查,但实际上并没有完全解决它。特别是,您不能键入 options: ts.CompilerOptions 之类的内容,因为 ts 不被视为命名空间 (error TS2503: Cannot find namespace 'ts'.)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-02
      • 2011-12-04
      • 1970-01-01
      • 2021-12-25
      • 2021-05-15
      • 2021-11-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多