typescript - 当组件具有非法类型时,Create React App withTypeScript 中的 Storybook 仍然可以编译

标签 typescript storyboard create-react-app

我正在尝试将 Storybook 添加到 Create React App,并在 TypeScript 中包含所有内容。我已经编译了它,但是当我在 React 组件中有非法类型然后创建 React App 错误(它应该)但 Storybook 仍然编译。

package.json 文件:

{
  "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"
  }
}

根 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;
};

最佳答案

尽管存在类型错误,Storybook 仍然编译的原因是 Create React App (CRA) 中的 Babel 预设 "react-app" 仅剥离 TypeScript 定义并发出所有文件,而无需进一步的编译器检查。

react-app / babel-preset-react-app可以将 CRA Babel 配置转移到其他构建中,例如 Storybook。在内部,它是 based@babel/preset-typescript ,它像这样处理 .ts/tsx 文件:

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

解决方案

1.) babel-preset-react-app

坚持使用 babel-preset-react-app 并使用 tsc 检查编译错误。 Microsoft/TypeScript-Babel-Starter存储库显示如何配置使用 tsc 运行类型检查的 npm 脚本:

"type-check": "tsc --noEmit",
"type-check:watch": "npm run type-check -- --watch",

这些脚本可以通过一些 IDE 任务进一步包装(例如,如果您使用 VS Code)。

2.) 成熟的编译器,例如awesome-typescript-loader

使用一些 Webpack TypeScript 加载器,例如 awesome-typescript-loader,它在捆绑期间使用完整的编译器 (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"]
}

关于typescript - 当组件具有非法类型时,Create React App withTypeScript 中的 Storybook 仍然可以编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57526387/

相关文章:

typescript 部分但不是完整的对象本身

angular - 筛选对象属性匹配接口(interface)

iOS - UIView 容器隐藏在键盘后面

node.js - 无法清除 npx 缓存并安装新版本的 create-react-app 即 5.0.0

reactjs - 如何使用具有多个页面和入口点的 React 和 TypeScript 设置 chrome 扩展?

angular - 必需的 Input() 参数仍然发出 "has no initializer"错误

ios - 返回 PKRevealController 时丢失左侧菜单

ios - Storyboard - 弹出框的委托(delegate)

reactjs - 创建 react 应用程序 - 访问 "On your network"不起作用

javascript - Typescript 中的 XHR 拦截器