Reputation: 222548
In the default TypeScript based create-react-app
project, only the first TS error is shown when the project is built with react-scripts
but all errors are shown when running tsc
.
The project was initialized with create-react-app foo --typescript
and only src/index.tsx
was modified after initialization:
src/index.tsx src/index.tsx
console.log(typeof nonExistentVar);
console.log(typeof nonExistentVar);
console.log(typeof nonExistentVar2);
console.log(typeof nonExistentVar2);
export {};
package.json
export {};
{
"name": "foo",
"version": "0.1.0",
"private": true,
"dependencies": {
"@types/jest": "24.0.15",
"@types/node": "12.6.8",
"@types/react": "16.8.23",
"@types/react-dom": "16.8.5",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-scripts": "3.0.1",
"typescript": "3.5.3"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve"
},
"include": [
"src"
]
}
npm start
shows only the first error:
Failed to compile.
C:/foo/src/index.tsx
TypeScript error in C:/foo/src/index.tsx(1,20):
Cannot find name 'nonExistentVar'. TS2304
> 1 | console.log(typeof nonExistentVar);
| ^
2 | console.log(typeof nonExistentVar2);
3 | export {};
And tsc
shows all errors at once:
src/index.tsx:1:20 - error TS2304: Cannot find name 'nonExistentVar'.
1 console.log(typeof nonExistentVar);
~~~~~~~~~~~~~~
src/index.tsx:2:20 - error TS2304: Cannot find name 'nonExistentVar2'.
2 console.log(typeof nonExistentVar2);
~~~~~~~~~~~~~~~
Found 2 errors.
How can I force start
and build
scripts to show all errors?
Upvotes: 6
Views: 2196
Reputation: 538
Found a better solution. No forking or ejecting necessary. You can write a very simple plugin that hooks into fork-ts-checker-webpack-plugin
to get all the errors and print them. Edit craco.config.js
to create the plugin class in my example I called it PrintAllWebpackErrorsPlugin
. Then instantiate the class in the webpack
section of the module.exports
. Don't forget to reset craco start
to apply the changes. The craco.config.js
file should look something like the following:
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
// This plugin uses a hook on the ForkTSCheckedWebpackPlugin to extract the errors and print them to console
class PrintAllWebpackErrorsPlugin {
apply(compiler) {
const hooks = ForkTsCheckerWebpackPlugin.getCompilerHooks(compiler);
hooks.done.tap("PrintAllWebpackErrorsPlugin", function(errors) {
errors.forEach(err => {
console.log(err.file)
console.log(`Typescript error in ${err.file}(${err.line},${err.character})`)
console.log(`${err.message} TS${err.code}`)
})
})
}
}
module.exports = {
reactScriptsVersion: "react-scripts" /* (default value) */,
style: {
modules: {
localIdentName: ""
},
css: {
loaderOptions: { /* Any css-loader configuration options: https://github.com/webpack-contrib/css-loader. */ },
loaderOptions: (cssLoaderOptions, { env, paths }) => { return cssLoaderOptions; }
},
sass: {
loaderOptions: { /* Any sass-loader configuration options: https://github.com/webpack-contrib/sass-loader. */ },
loaderOptions: (sassLoaderOptions, { env, paths }) => { return sassLoaderOptions; }
},
postcss: {
}
},
eslint: {
enable: false /* (default value) */,
mode: "extends" /* (default value) */ || "file",
configure: { /* Any eslint configuration options: https://eslint.org/docs/user-guide/configuring */ },
configure: (eslintConfig, { env, paths }) => { return eslintConfig; },
pluginOptions: { /* Any eslint plugin configuration options: https://github.com/webpack-contrib/eslint-webpack-plugin#options. */ },
pluginOptions: (eslintOptions, { env, paths }) => { return eslintOptions; }
},
babel: {
presets: [],
plugins: [],
loaderOptions: { /* Any babel-loader configuration options: https://github.com/babel/babel-loader. */ },
loaderOptions: (babelLoaderOptions, { env, paths }) => { return babelLoaderOptions; }
},
typescript: {
enableTypeChecking: true /* (default value) */
},
webpack: {
alias: {},
plugins: {
add: [
// Notice I'm instantiating the plugin here to include it.
new PrintAllWebpackErrorsPlugin(),
], /* An array of plugins */
remove: [], /* An array of plugin constructor's names (i.e. "StyleLintPlugin", "ESLintWebpackPlugin" ) */
},
configure: { /* Any webpack configuration options: https://webpack.js.org/configuration */ },
configure: (webpackConfig, { env, paths }) => { return webpackConfig; }
},
jest: {
babel: {
addPresets: true, /* (default value) */
addPlugins: true /* (default value) */
},
configure: { /* Any Jest configuration options: https://jestjs.io/docs/en/configuration */ },
configure: (jestConfig, { env, paths, resolve, rootDir }) => { return jestConfig; }
},
devServer: { /* Any devServer configuration options: https://webpack.js.org/configuration/dev-server/#devserver */ },
devServer: (devServerConfig, { env, paths, proxy, allowedHost }) => { return devServerConfig; },
plugins: [
{
plugin: {
overrideCracoConfig: ({ cracoConfig, pluginOptions, context: { env, paths } }) => { return cracoConfig; },
overrideWebpackConfig: ({ webpackConfig, cracoConfig, pluginOptions, context: { env, paths } }) => { return webpackConfig; },
overrideDevServerConfig: ({ devServerConfig, cracoConfig, pluginOptions, context: { env, paths, proxy, allowedHost } }) => { return devServerConfig; },
overrideJestConfig: ({ jestConfig, cracoConfig, pluginOptions, context: { env, paths, resolve, rootDir } }) => { return jestConfig },
},
options: {}
}
]
};
Upvotes: 1
Reputation: 3449
Here's what really happened. When fork-ts-checker-webpack-plugin
finds "type errors" in your code, it adds them to webpack's compilation errors for further processing and/or logging.
When the start
script from react-scripts
package is executed, the same errors array is trimmed to length 1. It then shows the first error (the only error) and stops the process.
When the build
script is run, it's the react-dev-utils/WebpackDevServerUtils
that does the same thing internally.
As pointed out by @amankkg, "you have to eject and tweak scripts/build.js
file" and the build process will work the way you want it to.
The real problem is with starting a dev server since react-dev-utils/WebpackDevServerUtils
is a part of node_modules and tweaking it locally is not a long-term fix. Your best bet is to fork the repo on github, make the required changes and use your forked version in your project(s).
Also, if you run the webpack config with just webpack-cli
, you'd see both the errors (along with a completed build).
Just eject the code, modify webpack's config file to set webpackEnv
from NODE_ENV
:
module.exports = function(webpackEnv) {
webpackEnv = webpackEnv || process.env.NODE_ENV //// add this line
const isEnvDevelopment = webpackEnv === 'development';
const isEnvProduction = webpackEnv === 'production';
and run the following:
npm i -g webpack-cli
NODE_ENV=development webpack --config config/webpack.config.js
Here's the sample output:
...
Entrypoint main = static/js/bundle.js ...
ERROR in /foo/src/index.tsx
ERROR in /foo/src/index.tsx(14,20):
TS2304: Cannot find name 'nonExistentVar'.
ERROR in /foo/src/index.tsx
ERROR in /foo/src/index.tsx(15,20):
TS2304: Cannot find name 'nonExistentVar2'.
...
There is one more thing you could try. There's this node package patch-package
that allows patching node_modules code locally and commits the said patch to your repo. I haven't used it but the docs explain the process pretty neatly. You should definitely check it out.
Upvotes: 4