Im trying to add Storybook to Create React App and have everything in TypeScript. I've got it compiling however when I have illegal types in a React component then Create React App errors (as it should) but Storybook still compiles.
package.json file:
{
"name": "hiit5",
"version": "0.1.0",
"private": true,
"dependencies": {
"@emotion/core": "^10.0.15",
"@types/jest": "^24.0.17",
"@types/node": "^12.7.2",
"@types/react": "^16.9.1",
"@types/react-dom": "^16.8.5",
"prop-types": "^15.7.2",
"react": "^16.9.0",
"react-docgen-typescript-webpack-plugin": "^1.1.0",
"react-dom": "^16.9.0",
"react-scripts": "3.1.0",
"typescript": "^3.5.3"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@babel/core": "^7.5.5",
"@storybook/addon-actions": "^5.1.11",
"@storybook/addon-info": "^5.1.11",
"@storybook/addon-knobs": "^5.1.11",
"@storybook/addon-links": "^5.1.11",
"@storybook/addons": "^5.1.11",
"@storybook/react": "^5.1.11",
"@types/storybook__react": "^4.0.2",
"awesome-typescript-loader": "^5.2.1",
"babel-core": "^6.26.3",
"babel-loader": "^8.0.6",
"prettier": "^1.18.2",
"react-docgen-typescript-loader": "^3.1.1",
"storybook-addon-jsx": "^7.1.5"
}
}
Root tsconfig.json:
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react"
},
"include": [
"src"
]
}
.storybook/config.ts
import { configure } from "@storybook/react";
// automatically import all files ending in *.stories.js
const req = require.context("../stories", true, /\.stories\.tsx$/);
function loadStories() {
req.keys().forEach(filename => req(filename));
}
configure(loadStories, module);
.storybook/tsconfig.ts
{
"compilerOptions": {
"outDir": "build/lib",
"module": "commonjs",
"target": "es5",
"lib": ["es5", "es6", "es7", "es2017", "dom"],
"sourceMap": true,
"allowJs": false,
"jsx": "react",
"moduleResolution": "node",
"rootDirs": ["src", "stories"],
"baseUrl": "src",
"forceConsistentCasingInFileNames": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": true,
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"noUnusedLocals": true,
"declaration": true,
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "build", "scripts"]
}
.storybook/webpack.config.js
module.exports = ({ config, mode }) => {
config.module.rules.push({
test: /\.(ts|tsx)$/,
loader: require.resolve("babel-loader"),
options: {
presets: [["react-app", { flow: false, typescript: true }]]
}
});
config.resolve.extensions.push(".ts", ".tsx");
return config;
};
The reason Storybook still compiles despite type errors is that Babel preset "react-app"
from Create React App (CRA) only strips off the TypeScript definitions and emits all files without further compiler checks.
react-app
/ babel-preset-react-app
can carry the CRA Babel configuration over to other builds, like Storybook. Internally, it is based on @babel/preset-typescript, which handles .ts/tsx files like this:
While Babel can take over compiling/transpiling – doing things like erasing your types and rewriting the newest ECMAScript features to work in older runtimes – it doesn’t have type-checking built in, and still requires using TypeScript to accomplish that. So even if Babel builds successfully, you might need to check in with TypeScript to catch type errors. Link
babel-preset-react-app
Stick with babel-preset-react-app
and use tsc
to check for compile errors. The Microsoft/TypeScript-Babel-Starter repository shows how to configure npm scripts that run a type check with tsc
:
"type-check": "tsc --noEmit",
"type-check:watch": "npm run type-check -- --watch",
Those scripts could be further wrapped by some IDE task (e.g. if you use VS Code).
awesome-typescript-loader
Use some Webpack TypeScript loader like awesome-typescript-loader
that makes use of the full compiler during bundling (Link).
webpack.config.js:
module.exports = ({ config, mode }) => {
config.module.rules.push({
test: /\.(ts|tsx)$/,
loader: "awesome-typescript-loader"
});
config.resolve.extensions.push(".ts", ".tsx");
return config;
};
tsconfig.json:
{
...
"compilerOptions": {
// if you use awesome-typescript-loader
"jsx": "react"
},
// include stories and src for type checking
"include": ["src", "stories"]
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With