Is it possible to have Material UI as peerDependency but keep its types as DevDependency?
I am building a component library using React + Typescript and the components are based on Material UI library, with Rollup as module bundler.
Here is an example of my IInputProps
type extending Material UI TextFieldProps
type.
import { TextFieldProps } from "@material-ui/core";
export type IInputProps = TextFieldProps & {...}
My goal is to set Material UI packages as a peerDependency, so it will use the material-ui package installed on the target project. I inserted the Material UI as peerDependency and set up rollup
with peerDepsExternal
plugin. When I tried to build the package, it throws the following error:
Cannot find module '@material-ui/core' or its corresponding type declarations.
The reason is related to this answer (What's the relationship of @material-ui/core and @types/material-ui?). Material-UI package contains its own type definitions (*.d.ts files
), so when I set it as peerDependency, the types/interfaces are missing. To solve this problem, I followed this solution (https://github.com/ezolenko/rollup-plugin-typescript2/issues/198) declaring each module on a src/@types/material-ui/index.d.ts file, but it raised another problem: I cannot use material-ui types/interfaces anymore.
With @material-ui/core
declared on my src/@types/material-ui/index.d.ts
file, the code points this error below.
Cannot use namespace 'TextFieldProps' as a type.ts(2709)
Exported type alias 'IInputProps' has or is using private name 'TextFieldProps'.ts(4081)
Now, I can only see these 2 solutions:
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
[x:string]:any
So, I would like to know if there is any way to have Material UI as peerDependency but keep its types as devDependencies, so I can bundle it with Material UI as peerDependency and also use its types on my package?
My configurations are following below:
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"
]
}
package.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",
},
...
I solved the problem by setting all my peerDependencies also as my devDependencies.
So, my package json was setting as below:
"peerDependencies": {
"@material-ui/core": "^4.11.4",
"react": "^16.8.0",
"react-dom": "^16.8.0",
},
"devDependencies": {
"@material-ui/core": "^4.11.4",
"react": "^16.8.0",
"react-dom": "^16.8.0",
...
Then I could get rid off some configurations:
All the others configurations remained the same.
reference: https://github.com/HarveyD/react-component-library/issues/40