Eslint/Tslint Config help (excluding files) - javascript

Recently in our project we migrated to use the #typescript-eslint/parser to slowly migrate from tslint. Everything has mostly been smooth but I have a small problem/question I can't work out.
Do I need to specify ignore files/patterns in both the tsconfig exclude array, as well as the ignorePatterns on the .eslintrc export object? What is the difference?
We have a messages.js file inside our src/lang directory that I'm trying to ignore but currently throws a lint error on our pre-commit hook, which got me wondering about this question and how these two setups work together.
Parsing error: "parserOptions.project" has been set for '#typescript-eslint/parser'
The file does not match your project config: src/lang/messages.js. The file must be included in at least one of the projects provided
I think my understanding of these intertwine is off, as when eslint runs, I thought the parserOptions would pick up the project rules from the tsconfig, where the js files are excluded.
Currently, the sections I'm talking about in our eslintrc looks like:
module.exports = {
parser: '#typescript-eslint/parser',
parserOptions: {
project: path.resolve(__dirname, './tsconfig.json'),
tsconfigRootDir: __dirname,
useJSXTextNode: true,
sourceType: 'module',
ecmaFeatures: {
modules: true,
jsx: true,
},
},
ignorePatterns: ['node_modules/**', '.storybook/**', 'src/stories/**', '*.scss', '*.js'] // ignoring here works
tsconfig:
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules", "src/**/*.js"], // exclude here doesn't work.
package.json:
"scripts": {
"lint": "tsc --project ./tsconfig.json --noEmit && eslint --ext=jsx,ts,tsx src"
},
​

ESLint passes the #typescript-eslint/parser plugin a list of files (which ESLint obtains from the command-line). The #typescript-eslint/parser plugin cannot control this list, so it does its best to act based upon the list it is given.
The error message is attempting to inform the user that ESlint is linting a file that is excluded from being parsed by the #typescript-eslint/parser plugin. From the plugin's perspective, there are two reasons this could occur:
The file was purposefully, explicitly excluded (by adding it to the tconfig exclude).
The user forgot to add the file to the tsconfig include.
In the latter case (which is much more common), the plugin wants to inform the user that their config is wrong, so that they can correct it. Hence the error message you saw.
In order to correctly exclude files from TSLint, one option is to use a .eslintignore file.
You can also change the eslint command to ignore the excluded files:
eslint ... --ignore-pattern "src/**/*.js"
(But be aware that the ignore pattern is relative to the current directory, not relative to the location of tsconfig etc.)
Alternatively, if you do want ESLint to lint the files (but still exclude them in tsconfig), you can consider providing a more inclusive tsconfig for #typescript-eslint/parser by creating a tsconfig.eslint.json file that extends from your normal tsconfig.
Also see these GitHub issues:
#typescript-eslint/parser doesn't ignore files, which is excluded by/in tsconfig.json #905
parse error on excluded files #1174
Exclude files in tsconfig without throwing an #typescript-eslint/parser error #1350

I was able to use the tsconfig exclude by using the JS config file .eslintrc.js and doing the following:
const tsConfig = require('./tsconfig.eslint.json');
module.exports = {
...
ignorePatterns: tsConfig.exclude,
};

Related

Confusing behavior when wiring together Rollup, ES modules, TypeScript, and JSX

The things I noted in the title - I started to learn them just recently. They are going not that smooth, so I have to ask this little question on StackOverflow.
What I require
Something to pack my stuff - here comes Rollup
Bare module imports for my own module files - using #rollup/plugin-node-resolve for this
Funny typed language - TypeScript and #rollup/plugin-typescript
React with JSX - it is react and react-dom packages, and typescript, which is able to process JSX
I read these docs to wire these tools together:
https://www.typescriptlang.org/tsconfig
https://www.npmjs.com/package/#rollup/plugin-typescript
I successfully used Rollup, #rollup/plugin-node-resolve, and TypeScript. But with addition of React things went odd.
Demo project
Please look at the example project I made for illustration:
https://github.com/Ser5/RollupWireBug
git clone https://github.com/Ser5/RollupWireBug.git
cd RollupWireBug/
npm install or yarn install
npm run build
The project structure is:
/
src/
js/ - only folder that contains my code
main.tsx - entry point
test-class.js - for testing bare import
buggy.tsx - should be excluded from building
dist/
bundle.js - Rollup output file
rollup.config.js
To my understanding the config should work like that:
resolve({
moduleDirectories: ['node_modules/', 'src/js/'],
extensions: ['.js', '.ts', '.jsx', '.tsx'],
}),
^ This should mean to bare import modules from node_modules/ and src/js/, searching for files with noted extensions.
And here comes the puzzling part:
typescript({
include: [
'./**/*',
//'src/js/**/*',
//"node_modules/**/*",
],
exclude: [
"node_modules/",
"dist/",
"src/buggy.tsx",
],
}),
^ This is how a configuration works for me. I must write ./**/* in the include - which seems odd for me, as I believe I don't need to include every file from the project root - I need only src/js/.
If instead of ./**/* I use src/js/**/*, or src/js/**/* with node_modules/**/* - Rollup refuses to build the project, screeching:
src/js/main.tsx → dist/bundle.js...
[!] Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)
src\js\main.tsx (7:13)
5:
6: let myName = 'Ser5';
7: let s = <h1>{myName}</h1>;
^
8: console.log(s);
Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)
It doesn't recognize the JSX syntax.
Because of ./**/* in the include I also need to have the exclude section - otherwise Rollup/TypeScript will crawl into src/buggy.js and even dist/, and try to build them as well.
tsconfig.json
I understand it as follows:
"baseUrl": "./",
"paths": {
"*": [
"node_modules/*",
"src/js/*",
],
},
^ "Go search modules in node_modules/ and src/js/ directories."
"outDir": "tsout",
^ Really no idea WTF is this. Looks like some temporary folder.
And if instead of this part in rollup.config.js
typescript({
include: [
'./**/*',
],
...
}),
I write the same thing in tsconfig.json
{
include: [
'./**/*',
],
"compilerOptions": {
...
The project still doesn't build - displaying Error: Unexpected token for JSX syntax.
Questions
Where am I wrong?
Why for #rollup/plugin-typescript I have to include ./**/* right from the root, and block some files with include section? Why can't I simply write src/js/**/* ?
Why include works only for #rollup/plugin-typescript? And I can't write that include in tsconfig.json?
Will try to give you some hints:
outDir option says where the JavaScript files will be generated
#rollup/plugin-typescript will load any compilerOptions from the tsconfig.json file by default. So if you are passing any option to that (like you did in your repo) it will override those ones that you set in tsconfig.json. Might be better to decide where to config stuff for TS
Specifically for your error. See docs here.
You have to do this basically:
import jsx from 'acorn-jsx';
import typescript from '#rollup/plugin-typescript';
export default {
// … other options …
acornInjectPlugins: [jsx()],
plugins: [typescript({ jsx: 'preserve' })]
};
Check Vite out by the way if you want to avoid all this config shenanigans! :)

ESLint: prevent from being linted non-standard files extensions

My .estintrc.yaml:
parser: "#typescript-eslint/parser"
parserOptions:
sourceType: module
project: tsconfig.json
tsconfigRootDir: ./
env:
es6: true
browser: true
node: true
mocha: true
plugins:
- "#typescript-eslint"
With it, I have many errors like:
D:\*****\project\package.json
0:0 error Parsing error: "parserOptions.project" has been set for #typescript-eslint/parser.
The file does not match your project config: package.json.
The extension for the file (.json) is non-standard. You should add "parserOptions.extraFileExtensions" to your config
I did not ask to check .json files.
I want .ts and .vue files only will be being linted.
Which setting I missed?
When you call eslint you can use the —ext flag to tell it what file types to check. To limit file types in the config file, you would have to wrap all rules and extended configs within an override.
I would however also recommend eslint-plugin-json as alternate solution.

Webpack using Typescript: Common settings in both configs, so which take precedence?

I am in the initial stages of converting a javascript (with webpack) project into a typescript project and one of the many confusions I have is that their appears to be some configuration settings that can appear in webpack and typescript, so which takes precedence?
(I'm currently working on a node cli application).
Eg, the primary example is which files are included in compilation.
In webpack config, you can specify which input files are selected with rules:
module: {
rules: [
{
test: /index.ts/,
use: 'shebang-loader'
},
{
test: /\.ts(x?)$/,
use: 'ts-loader'
},
{
test: /\.json$/,
use: 'json-loader'
}
]
},
As you can see from above, I'm using various loaders for different file types.
Then my initial tsconfig.json is as follows:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"noImplicitAny": true,
"lib": [
"es5", "es2015", "es6", "dom"
]
},
"include": [
"lib/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
So what is the true nature of the interaction between webpack and typescript? I have not been able to discern this from typescript or webpack documentation. Both appear to be able to specify the input files that are included in compilation.
Another (probably better example) is the output file. In webpack config I have the following:
output: {
libraryTarget: 'commonjs',
path: path.join(__dirname, 'dist'),
filename: 'application-bundle.js'
}
which defines 'application-bundle.js' is the output file inside the 'dist' folder.
In the tsconfig, you can have something like the following:
"outFile": "./dist/application-bundle.js",
(I currently do not define an outFile property, but I know you can do so, but in being able to do so, brings up ambiguities and hence confusion). So in this scenario, does webpack override typescript or vice-versa? What is the recommended strategy?
There are probably more typescript/webpack crossovers that are going to cause confusion, but the 2 that I have described so far are the most upfront and pressing issues I need to understand, thanks.
EDIT: Having thought about it, I also need another clarification. I am guessing when you build a TS/WP project, the TS compiler runs first creates all the .js files (let's say in the .dist folder). Then webpack bundles all the generated .js files. So assuming this is correct, do I then need to configure webpack to use as its input the .js files in the dist folder instead of the .js files inside the project source (ie everything under ./lib which is where my source js files are)?
I was hoping to convert my project in an incremental manner so what I have just said does not really fit my needs. Webpack would need to pick up some .js files from ./dist and some files from ./lib which have not yet been converted to typescript. I don't know how to modify the project for incremental upgrade.
[...] there appears to be some configuration settings that can appear in webpack and typescript, so which takes precedence?
You are right on the point that there is some natural redundancy in the configuration when Webpack is combined with TypeScript. Lets pick up your first question:
which files are included in compilation? [...] Another example is the output file. [...] So in this scenario, does webpack override typescript or vice-versa? What is the recommended strategy?
Simply spoken, both TypeScript and Webpack process/transform input files and emit the output in a target directory structure or file bundle(s) - both need some input/output configuration info. TypeScript compiler can run on its own, and also be integrated as file processor as part of a bigger Webpack build. With outFile option TypeScript can even be seen as a mini-bundler on its own, as it bundles all .ts-files to a single target file.
To answer the question, if TypeScript or Webpack configuration takes precedence, it is important to understand, how Webpack works. I'll quote one of your assumptions here:
I am guessing when you build a TS/WP project, the TS compiler runs first creates all the .js files (let's say in the .dist folder). Then webpack bundles all the generated .js files.
That is not quite correct. But good you said that, as it sheds more light on your core understanding problem. Everything in Webpack starts with the entry point you specify in the config - if you will, that's the input. From this entry module, webpack considers all other transitively imported modules (e.g. via import or require) and creates a dependency tree.
Every file in the dependency tree can optionally be transformed by Loaders, which can also be chained like a file processing pipeline. So ts-loader and the underlying TypeScript compiler apply transformations for .ts/.tsx files with test: /\.ts(x?)$/ predicate.
All in all you see, that Webpack considers your entry file, which leads to a bunch of further imported .ts/.tsx files (amongst your other file types, we neglect them here). And for each single file, the TypeScript loader will be invoked in the course of the loader processing pipeline. Therefore, it is inherent that TypeScript I/O config will be ignored and Webpack's entry/output configuration takes precedence in the build. All other TypeScript related settings are taken from tsconfig.json, as described in the ts-loader docs: "The tsconfig.json file controls TypeScript-related options so that your IDE, the tsc command, and this loader all share the same options."
I was hoping to convert my project in an incremental manner
It is perfectly fine to migrate from JavaScript to TypeScript in a stepwise manner!
Hope, that helps.

How to generate d.ts and d.ts.map files using webpack?

I can't find a way to generate d.ts and d.ts.map files using webpack. babel-loader only generates js and js.map files. I also need d.ts and d.ts.map files (which I was able to generate using tsc command) as shown in this picture:
Here is a minimal repo that contains all the settings: https://github.com/stavalfi/lerna-yarn-workspaces-example
More Details
I moved to Lerna + yarn. One of my packages is core (will be used in other packages) which is written in TS and JS.
I'm using webpack 4,babel-loader 8 for ts-to-js.
The other packages are trying to find type definitions and implementation of my core package but I was only able to generate index.js and index.js.map with webpack:
output: {
path: distPath,
filename: 'index.js',
},
{
"extends": "../tsconfig.settings.json",
"compilerOptions": {
"declaration": true,
"declarationMap": true,
"declarationDir": "dist",
"rootDir": "src",
"outDir": "dist"
}
}
When I compile with tsc (without webpack), everything is working great as I showed in the picture above.
Does my strategy is wrong? what should I do?
I have tried a lot of plugins that generate d.ts files but they don't work and doesn't create d.ts.map files.
I already tried: typescript-declaration-webpack-plugin, npm-dts-webpack-plugin, dts-bundle-webpack, #ahrakio/witty-webpack-declaration-files. (They are listed in the package.json of core so you can clone and play with it).
Running ts-loader before babel-loader will do the trick.
Specifying that you want declaration files in config is all you need.
If you are using an absolute path, the output d.ts files will also contain absolute paths which are useless and will result in typescript compilation errors.
To fix that, I wrote a plugin to convert an absolute path to a relative path:
https://github.com/stavalfi/babel-plugin-module-resolver-loader
You can call the Typescript compiler tsc directly to do that.
Use tsc --declaration to output a .d.ts file and tsc --declarationMap to generate the corresponding map file.
You can find more documentation here:
https://www.typescriptlang.org/docs/handbook/compiler-options.html

Why ngc partially ignore compileroptions.outDir? Does a workaround exist?

I have a tsconfig.json which specifies an outDir. The reason is that I want to separate the generated JavaScript output from the TypeScript sources.
So:
"compilerOptions": {
...
"outDir": "target/",
...
}
This works very well, until I compile the project with the typescript compiler only. All generated javascript output is created in the target/ directory.
But, if I call it with the angular compiler (ngc, it is essentially a wrapper around the tsc typescript compiler), we have an additional build step. It compiles the template files and components into typescript, which will be compiled further to javascript by the tsc.
These intermediary typescript files have the *.ngfactory.ts or *.ngsummary.json extension.
Now my problem is, that the ngc command generates these files still in my src/ directory, totally ignoring my outDir setting in my tsconfig.json.
What is the cause of this problem? Does any useful workaround exist?
Extension: regarding comments, ng from the angular-cli can do this. This leads to a side-question, how does it do with the ngc?
The cause of the problem was that ngc has some additional options in tsconfig.json what I didn't add.
The following settings in tsconfig.json do what I want.
"angularCompilerOptions": {
"genDir": "aot",
"skipMetadataEmit" : true
}

Categories

Resources