【问题标题】:Why does SVGR not generate a TypeScript declaration file in my esbuild configuration?为什么 SVGR 没有在我的 esbuild 配置中生成 TypeScript 声明文件?
【发布时间】:2022-06-20 03:56:34
【问题描述】:

我正在使用 TypeScript 创建一个 SVG 图标库。到目前为止,SVGR 非常棒,但我需要的最后一点是生成的类型,以允许将 titleref 传递给捆绑的组件。

复制

我不确定看到哪些内容可能会有所帮助,因此我将包含一个 repo 和一些代码示例。但是通过以下设置,svgr 正在从 SVG 导入创建组件,但没有生成任何类型。结果,每当我尝试使用此包中的图标时,都会警告我找不到它的声明文件。

POC 回购:https://github.com/yuschick/icon-demo

src/index.ts

export { default as TestIcon } from "./svg/test.svg";
export { default as ArrowThinLeft } from './svg/arrow-thin-left.svg';

package.json

{
  "module": "dist/index.js",
  "types": "dist/index.d.ts",
  "type": "module",
  "scripts": {
    "build": "node esbuild.config.js",
  },
  "devDependencies": {
    "esbuild": "^0.14.39",
    "esbuild-plugin-svgr": "^1.0.1",
    "typescript": "^4.6.3"
  }
}

esbuild.config.js

import esbuild from "esbuild";
import svgr from "esbuild-plugin-svgr";

esbuild.build({
    bundle: true,
    entryPoints: ["src/index.ts"],
    external: ["react"],
    format: "esm",
    // minify: true,
    outfile: "dist/index.js",
    plugins: [svgr({ titleProp: true, ref: true, expandProps: false, typescript: true })],
})
  .catch(() => process.exit(1));

tsconfig.json

{
  "compilerOptions": {
    "allowJs": true,
    "allowSyntheticDefaultImports": true,
    "alwaysStrict": true,
    "baseUrl": "src",
    "checkJs": true,
    "declaration": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "isolatedModules": true,
    "lib": ["dom", "dom.iterable", "esnext"],
    "module": "esnext",
    "moduleResolution": "node",
    "noEmit": true,
    "outDir": "dist",
    "resolveJsonModule": true,
    "skipLibCheck": true,
    "strict": true,
    "target": "esnext"
  },
  "include": ["src", "global.d.ts"]
}

global.d.ts

declare module '*.svg' {
    const content: string;
    export default content;
}

预期行为

通过将typescript: true 传递给svgr 选项,我期望根据生成的组件生成index.d.tsx 文件。

根据 SVGR 文档:

生成带有TypeScript 类型的 .tsx 文件。

注意:虽然我在 ESBuild 中使用 SVGR,但在尝试使用 Rollup 时也存在同样的问题。

【问题讨论】:

    标签: typescript svg types .d.ts esbuild


    【解决方案1】:

    问题

    通过将typescript: true 传递给svgr 选项,我期望根据生成的组件生成index.d.tsx 文件。

    这种预期是不正确的。如果您指定 typescript 选项而不是 .d.ts 文件,SVGR 将仅生成 .tsx 文件。来自documentation(你也找到了):

    打字稿

    使用 TypeScript 类型生成 .tsx 文件。

    但是,即使指定了此选项,SVGR 也不会生成 .tsx 文件,因为您在 esbuild 插件中使用它。 esbuild-plugin-svgr 在底层利用了来自 @svgr/coretransform 函数(参见 esbuild-plugin-svgr/index.js:L4)。 transform function 仅将 SVG 转换为 JSX 或 TSX,但从不写入输出。 @svgr/cli 处理将输出写入文件,例如参见 @svgr/cli/src/dirCommand.ts

    解决方案

    我认为你有两个选择:

    从esbuild中分离出SVGR,然后生成.d.ts文件

    换句话说,停止使用esbuild-plugin-svgr 并改用@svgr/cli。然后,您必须在 esbuild 之前运行 SVGR;手动,在脚本中链接命令或使用npm's pre-script hook。之后你必须生成一个.d.ts file。虽然,看着esbuild#95,它似乎并不支持开箱即用。您可能想探索其中列出的建议,包括:

    • 使用 TypeScript 编译器发出声明文件 (tsc --emitDeclarationOnly)
    • 使用插件如esbuild-plugin-d.ts

    您的构建链最后可能如下所示:

    1. 使用 @svgr/cli 从 SVG 生成 .tsx 文件。
    2. 使用 esbuild 打包。
    3. 生成.d.ts 文件,可以使用tsc 作为单独的步骤,也可以使用esbuild 插件与上述步骤合并。

    从您的 JavaScript 包中生成一个 .d.ts 文件

    如果出于某种原因您真的想保留当前的构建配置,您可以使用 tsc dist/index.js --declaration --allowJs --emitDeclarationOnly 从 JavaScript 捆绑文件生成 .d.ts 文件(请参阅 TypeScript documentation)。需要注意的是,TypeScript 可能无法推断所有类型,因此您的类型声明文件可能不完整。

    【讨论】:

    • 哇。非常感谢您的回复。这里有很多很好的信息可供参考,我相信这会推动我前进。谢谢! :)
    • 只是作为更新。我在技术上使用 svgr/cli 使用我的 prebuild 脚本,使用 esbuild 构建脚本来捆绑 prebuild 的结果,然后 postbuild 在捆绑的文件上运行 tsc。此刻这感觉有点脆弱,但你所描述的一切都按预期工作。再次感谢!
    【解决方案2】:

    在尝试将 typescript 类型与 rollup-plugin-dts 插件捆绑时遇到了类似的 svgr 问题。

    通过创建单个 icon.d.ts 文件来解决它:

    import { SVGProps } from 'react';
    declare const ReactComponent: (props: SVGProps<SVGSVGElement>) => JSX.Element;
    export { ReactComponent };
    

    然后像这样使用别名插件:

    import alias from '@rollup/plugin-alias';
    ...
          plugins: [
            alias({
              entries: [
                {
                  find: /^.*\.svg$/,
                  replacement: 'src/types/icon.d.ts',
                },
              ],
            }),
            dts(),
          ],
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-20
      • 2019-01-10
      • 2021-02-18
      • 2020-03-22
      • 2019-04-03
      • 1970-01-01
      相关资源
      最近更新 更多