为什么SVGR不生成一个TypeScript声明文件在我的esbuild配置?



我正在TypeScript中创建一个SVG图标库。到目前为止,SVGR已经非常出色了,但是我需要的最后一部分是生成的类型,以允许将titleref传递给绑定的组件。

生殖

我不确定看到什么可能会有帮助,所以我将包括一个repo和一些代码示例。但是在下面的设置中,svgr从SVG导入创建组件,但是没有生成类型。因此,每当我尝试使用这个包中的图标时,系统都会警告我找不到该图标的声明文件。

POC Repo: 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: true传递到svgr选项,我期望根据生成的组件生成index.d.tsx文件。

这个期望是不正确的。如果您指定了typescript选项而不是.d.ts文件,SVGR将只生成.tsx文件。从文档(您也找到了):

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

然而,即使指定了这个选项,SVGR也不会生成.tsx文件,因为您在esbuild插件中使用了这个选项。引擎盖下的esbuild-plugin-svgr利用@svgr/coretransform函数(参见esbuild-plugin-svgr/index.js:L4)。transform函数只将SVG转换为JSX或TSX,但从不写入输出。@svgr/cli处理将输出写入文件,例如参见@svgr/cli/src/dirCommand.ts

<标题>

解决方案我认为你有两个选择:

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

换句话说,停止使用esbuild-plugin-svgr而使用@svgr/cli。然后,您必须在esbuild之前运行SVGR;可以手动将命令链接到脚本中,也可以使用npm的pre-script钩子。之后,您必须生成一个.d.ts file。虽然,看看esbuild#95,它似乎没有开箱即用的支持。您可能想要探索其中列出的建议,包括:

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

您的构建链可能在末尾看起来像这样:

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

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

如果出于某种原因你真的想要保持你当前的构建配置,你可以用tsc dist/index.js --declaration --allowJs --emitDeclarationOnly从你的JavaScript bundle文件中生成一个.d.ts文件(参见TypeScript文档)。注意:TypeScript可能无法推断出所有的类型,所以你可能会得到一个不完整的类型声明文件。

在使用rollup-plugin-dts插件捆绑typescript类型时遇到了类似的问题。

通过创建一个icon. d.s文件来解决这个问题:

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(),
],

最新更新