是否可以将 Material UI 作为 peerDependency 但将其类型保持为 DevDependency?
我正在使用 React + Typescript 构建一个组件库,这些组件基于 Material UI 库,其中 Rollup 作为模块捆绑器。
这是我的IInputProps
类型扩展 Material UITextFieldProps
类型的示例。
import { TextFieldProps } from "@material-ui/core";
export type IInputProps = TextFieldProps & {...}
我的目标是将 Material UI 包设置为 peerDependency,因此它将使用安装在目标项目上的 material-ui 包。我将 Material UI 作为 peerDependency 插入并rollup
使用peerDepsExternal
插件进行设置。当我尝试构建包时,它会引发以下错误:
Cannot find module '@material-ui/core' or its corresponding type declarations.
原因与这个答案有关(@material-ui/core 和 @types/material-ui 有什么关系?)。Material-UI 包包含它自己的类型定义 ( *.d.ts files
),因此当我将其设置为 peerDependency 时,类型/接口丢失了。为了解决这个问题,我遵循了这个解决方案(https://github.com/ezolenko/rollup-plugin-typescript2/issues/198)在 src/@types/material-ui/index.d.ts 文件中声明每个模块,但它引发了另一个问题:我不能再使用 material-ui 类型/接口了。
在@material-ui/core
我的src/@types/material-ui/index.d.ts
文件中声明后,代码在下面指出了这个错误。
Cannot use namespace 'TextFieldProps' as a type.ts(2709)
Exported type alias 'IInputProps' has or is using private name 'TextFieldProps'.ts(4081)
现在,我只能看到这两个解决方案:
- 将整个材料 ui 包保存在我的库中并丢失包大小:
Library with Material UI packages as peerDependency
npm notice package size: 101.0 kB
npm notice unpacked size: 493.6 kB
Library with Material UI packages
npm notice package size: 1.2 MB
npm notice unpacked size: 6.0 MB
- 将 Material UI 用作 peerDependency,但会丢失 Material UI 类型/接口和 lint(通过向我的类型/接口添加一个接受任何道具的属性 -允许其他属性的 TypeScript 接口)。
[x:string]:any
所以,我想知道是否有任何方法可以将 Material UI 作为 peerDependency 但将其类型保留为 devDependencies,所以我可以将它与 Material UI 捆绑为 peerDependency 并在我的包中使用它的类型?
我的配置如下:
src/@types/material-ui/index.d.ts
declare module "@material-ui/core";
rollup.config.js
import peerDepsExternal from "rollup-plugin-peer-deps-external";
import resolve from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import image from "@rollup/plugin-image";
import typescript from "rollup-plugin-typescript2";
const packageJson = require("./package.json");
export default {
input: "src/index.ts",
output: [
{
file: packageJson.main,
format: "cjs",
sourcemap: true
},
{
file: packageJson.module,
format: "esm",
sourcemap: true
}
],
plugins: [
peerDepsExternal(),
resolve(),
commonjs(),
image(),
typescript({ useTsconfigDeclarationDir: true })
]
};
tsconfig.json
{
"compilerOptions": {
"rootDir": "src",
"declaration": true,
"declarationDir": "build",
"module": "esnext",
"target": "es5",
"lib": ["es6", "dom", "es2016", "es2017"],
"sourceMap": true,
"jsx": "react",
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"typeRoots": ["./src/@types"]
},
"include": ["src/**/*"],
"exclude": [
"node_modules",
"build",
"storybook-static",
"src/**/*.stories.tsx",
"src/**/*.test.tsx"
]
}
包.json
...
"main": "build/index.js",
"module": "build/index.esm.js",
...
,
"peerDependencies": {
"@material-ui/core": "^4.11.4",
"react": "^16.8.0",
"react-dom": "^16.8.0",
},
...