网站搜索

json - 我如何限制 `resolveJsonModule` 的作用范围?


我正在做一个使用 Typescript 和 webpack 的项目。我必须导入 json 文件,并且必须用两种方式导入:

  • 我必须将项目的package.json作为模块导入。这已经在之前实现过了。
  • 必须以可通过 URL 加载的资源方式导入一些 JSON 模式。这就是我现在正在做的事情。

使用 package.json(已实现)

要导入 package.json,tsconfig.json 包含:

{
  "compilerOptions": {
    "resolveJsonModule": true,
    "paths": {
      "package.json": ["./package.json"]
    }
  },
}

并且 webpack 配置有:

  /**
   * Determine the array of extensions that should be used to resolve modules.
   */
  resolve: {
    extensions: [".js", ".ts", ".tsx", ".json"],
    plugins: [
      new TSConfigPathsPlugin({
        configFile: path.join(__dirname, "../../tsconfig.json"),
        logLevel: "info",
        extensions: [".js", ".jsx", ".ts", ".tsx"],
        mainFields: ["browser", "main"],
        baseUrl: tsConfig.baseUrl,
      }),
    ],
  },

这就是 package.json 的用法:

import packageJson from "package.json";

//...

const release = `${packageJson.version}-${process.platform}`;

这是完全类型安全的:ts 会检查我的 package.json 是否有 version 字段。这按预期工作,我不想破坏它。

使用 schema JSON 文件(我正在实现的)

为了添加对 JSON 模式的支持,我已将它们添加为文件名匹配 .schema.json$ 的文件,并已将其添加到 webpack 配置中:

  module: {
    rules: [
      {
        test: /\.schema.json$/,
        type: "asset/resource",
      },
    ],
  },

并且这是针对全局类型声明文件的:

declare module "*.schema.json" {
  declare const uri: string;
  export default uri;
}

我以为通过这样做,Typescript 会将导入这样的文件解释为一个简单的字符串。我一直在按照这个例子操作。

然而,当我在项目中导入模式文件时:

import someSchemaUri from "./schemas/some-name.schema.json";

// ...

uri = someSchemaUri;

我仍然收到类型错误:

类型 '{ ... }' 不能赋值给类型 'string'。

更改 resolveJsonModule

如果我将 resolveJsonModule 选项设置为 false,这个问题就会消失,但从上一节导入 package.json 开始会报错:

模块 'package.json' 已解析为 'secret/path/package.json',但未使用 '--resolveJsonModule'。

我如何配置我的项目,使得 TypeScript 会将这些文件解释为 string,但同时在从上一部分导入 package.json 时不会丢失类型安全?

答案#1

据我所知,一旦设置了 --resolveJsonModule,就无法覆盖 json 类型。你是否可以考虑禁用该标志并手动为 package.json 编写类型?这并不耗时,因为你只使用一个 package.json 字段。

declare module '*.schema.json' {
    const uri: string;
    export default uri;
}

declare module '*package.json' {
    const content: {
        version: string;
    };
    export default content;
}