ASP.NET Visual Studio [不是代码] 2019 中的 5 个(核心)网站,带有 TypeScript 和 Node(或 ESM)模块?

ASP.NET 5 (Core) Website with TypeScript and Node (or ESM) modules in Visual Studio [not Code] 2019?

所以我按照 this guide 在 ASP.NET 5 网站项目(使用 Razor Page)中设置了 TypeScript。我想使用 Node 模块进行 TypeScript 打字,而不是仅仅导入为 any.

现在我想添加一个 Node 模块,比如 EthersJS,所以我有:

    "dependencies": {
        "ethers": "^5.4.1"
    }

此代码无法编译:

import { ethers } from "ethers";

export class EthService {

    pro: ethers.providers.BaseProvider;

    constructor() {
        const pro = this.pro = new ethers.providers.WebSocketProvider("");
    }

    async getBlockNumberAsync() {
        return await this.pro.getBlockNumber();
    }

}

除非我将 "moduleResolution": "Node" 添加到 tsconfig.json。显然,这实际上不会 运行 在浏览器中。

我应该如何设置它以便以某种方式编译 Node 模块?我认为如果我能做到以下任何一项,问题就可以解决:

更新:我认为第三种可能性也非常好,如果我可以像这样声明导入(我只会将 ESM 文件添加到全局范围):

declare import { ethers } from "ethers";

以上选项是否可行?或者有什么办法吗?谢谢。

注意:我知道有 Triple-Slash Directives,它可能会解决我的问题,但我还不太明白他们的作用。

当前gulpfile.js:

/// <binding AfterBuild='default' Clean='clean' />
/*
This file is the main entry point for defining Gulp tasks and using Gulp plugins.
Click here to learn more. http://go.microsoft.com/fwlink/?LinkId=518007
*/
var gulp = require("gulp");
var del = require("del");
var paths = {
    scripts: ["Scripts/**/*.js", "Scripts/**/*.ts", "Scripts/**/*.map"],
};
gulp.task("clean", function () {
    return del(["wwwroot/Scripts/**/*"]);
});
gulp.task("default", function () {
    gulp.src(paths.scripts).pipe(gulp.dest("wwwroot/Scripts"));
});

tsconfig.json:

{
    "compilerOptions": {
        "noImplicitAny": true,
        "noEmitOnError": true,
        "removeComments": false,
        "sourceMap": true,
        "target": "ESNext",
        "module": "ESNext",
        "moduleResolution": "Node"
    },
    "exclude": [
        "wwwroot",
        "node_modules"
    ],
    "compileOnSave": true
}

我可以通过使用独立的 ethers.js 脚本文件将 ethers 命名空间暴露给全局范围来解决问题:

<script defer src="/libs/ethers.umd.min.js" asp-append-version="true"></script>

现在您需要告诉 TypeScript 在全局范围内有一个 ethers“东西”(namespace/module)。感谢 this article,我找到了解决方案。创建一个 .d.ts 文件(任何都可以,我将其命名为 globals.d.ts):

import { ethers as eth } from "ethers";

declare global {

    // @ts-ignore: export typing
    export { eth as ethers };

}

现在您可以在任何地方使用 ethers 而无需任何声明。例如我的整个 EthService.ts 文件:

export class EthService {

    pro: ethers.providers.WebSocketProvider;

    init(server: string) {
        this.pro = new ethers.providers.WebSocketProvider(server);
    }

    async getBlockNoAsync() {
        return await this.pro.getBlockNumber();
    }

}