在 TS 文件中导入时找不到节点本机模块

Node native module not found when imported in TS file

我正在处理 Svelte 和 TypeScript 项目,运行 遇到导入本机 Node 模块的问题。例如,键入

import { createInterface } from "readline";

.ts.svelte 文件中 returns 一条警告说

Plugin typescript: @rollup/plugin-typescript TS2307: Cannot find module 'readline' or its corresponding type declarations.

但是,如果我在 .js 文件中键入相同的内容,一切仍然正常。

我在 node_modules 中已有 @types/node。很想知道如何解决这个问题。我正在使用 Node 15.3.0 和 npm 7.5.4。这是我的配置文件,供参考:

{
  "extends": "@tsconfig/svelte/tsconfig.json",

  "include": ["src/**/*"],
  "exclude": ["node_modules/*", "__sapper__/*", "public/*"],

  "compilerOptions": {
    "baseUrl": ".",

    /* Strict Type-Checking Options */
    "strict": true,                           /* Enable all strict type-checking options. */
    "noImplicitAny": true,                    /* Raise error on expressions and declarations with an implied 'any' type. */
    "strictNullChecks": true,                 /* Enable strict null checks. */
    "strictFunctionTypes": true,              /* Enable strict checking of function types. */
    "strictBindCallApply": true,              /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
    "strictPropertyInitialization": true,     /* Enable strict checking of property initialization in classes. */
    "noImplicitThis": true,                   /* Raise error on 'this' expressions with an implied 'any' type. */
    "alwaysStrict": true,                     /* Parse in strict mode and emit "use strict" for each source file. */

    /* Additional Checks */
    "noUnusedLocals": true,                   /* Report errors on unused locals. */
    "noUnusedParameters": true,               /* Report errors on unused parameters. */
    "noImplicitReturns": true,                /* Report error when not all code paths in function return a value. */
    "noFallthroughCasesInSwitch": true,       /* Report errors for fallthrough cases in switch statement. */
  }
}
{
  "name": "svelte-app",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "build": "rollup -c",
    "autobuild": "rollup -c -w",
    "dev": "run-p start:dev autobuild",
    "start": "sirv public --single",
    "start:dev": "sirv public --single --dev",
    "validate": "svelte-check"
  },
  "devDependencies": {
    "@rollup/plugin-commonjs": "^17.0.0",
    "@rollup/plugin-node-resolve": "^11.0.0",
    "@rollup/plugin-typescript": "^8.0.0",
    "@tsconfig/svelte": "^1.0.0",
    "npm-run-all": "^4.1.5",
    "rollup": "^2.3.4",
    "rollup-plugin-css-only": "^3.1.0",
    "rollup-plugin-livereload": "^2.0.0",
    "rollup-plugin-svelte": "^7.0.0",
    "rollup-plugin-terser": "^7.0.0",
    "svelte": "^3.0.0",
    "svelte-check": "^1.0.0",
    "svelte-preprocess": "^4.0.0",
    "tslib": "^2.0.0",
    "typescript": "^4.0.0"
  },
  "dependencies": {
    "sirv-cli": "^1.0.0"
  }
}
import svelte from 'rollup-plugin-svelte';
import commonjs from '@rollup/plugin-commonjs';
import resolve from '@rollup/plugin-node-resolve';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
import sveltePreprocess from 'svelte-preprocess';
import typescript from '@rollup/plugin-typescript';
import css from 'rollup-plugin-css-only';

const production = !process.env.ROLLUP_WATCH;

function serve() {
    let server;

    function toExit() {
        if (server) server.kill(0);
    }

    return {
        writeBundle() {
            if (server) return;
            server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
                stdio: ['ignore', 'inherit', 'inherit'],
                shell: true
            });

            process.on('SIGTERM', toExit);
            process.on('exit', toExit);
        }
    };
}

export default {
    input: 'src/main.ts',
    output: {
        sourcemap: true,
        format: 'iife',
        name: 'app',
        file: 'public/build/bundle.js'
    },
    plugins: [
        svelte({
            preprocess: sveltePreprocess({ sourceMap: !production }),
            compilerOptions: {
                // enable run-time checks when not in production
                dev: !production
            }
        }),
        // we'll extract any component CSS out into
        // a separate file - better for performance
        css({ output: 'bundle.css' }),

        // If you have external dependencies installed from
        // npm, you'll most likely need these plugins. In
        // some cases you'll need additional configuration -
        // consult the documentation for details:
        // https://github.com/rollup/plugins/tree/master/packages/commonjs
        resolve({
            browser: true,
            dedupe: ['svelte']
        }),
        commonjs(),
        typescript({
            sourceMap: !production,
            inlineSources: !production
        }),

        // In dev mode, call `npm run start` once
        // the bundle has been generated
        !production && serve(),

        // Watch the `public` directory and refresh the
        // browser on changes when not in production
        !production && livereload('public'),

        // If we're building for production (npm run build
        // instead of npm run dev), minify
        production && terser()
    ],
    watch: {
        clearScreen: false
    }
};
{
  "$schema": "https://json.schemastore.org/tsconfig",
  "display": "Svelte",

  "compilerOptions": {
    "moduleResolution": "node",
    "target": "es2017",
    /** 
      Svelte Preprocess cannot figure out whether you have a value or a type, so tell TypeScript
      to enforce using `import type` instead of `import` for Types.
     */
    "importsNotUsedAsValues": "error",
    "isolatedModules": true,
    /**
      To have warnings/errors of the Svelte compiler at the correct position,
      enable source maps by default.
     */
    "sourceMap": true,
    /** Requests the runtime types from the svelte modules by default. Needed for TS files or else you get errors. */
    "types": ["svelte"],

    "strict": false,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}

谢谢!

我明白了。而不是

import { createInterface } from "readline";

应该是

import { createInterface } from "node:readline";

显然,这是在我当前的设置中引用本机 Node 模块的正确方法。不过很想知道为什么。

您从集 "types": ["svelte"] 扩展的基本 tsconfig 关闭了其他环境类型,如 @types/node 的环境类型。要解决此问题,请将 "types": ["svelte", "node"] 添加到您的 tsconfig.json.