Skip to content

Bug: config-helper.ts has unexpected behavior when base config contains only meta keys #10754

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
4 tasks done
jeremy-code opened this issue Feb 1, 2025 · 2 comments · Fixed by #11065
Closed
4 tasks done
Labels
accepting prs Go ahead, send a pull request that resolves this issue bug Something isn't working locked due to age Please open a new issue if you'd like to say more. See https://typescript-eslint.io/contributing. package: typescript-eslint Issues related to the typescript-eslint package

Comments

@jeremy-code
Copy link
Contributor

jeremy-code commented Feb 1, 2025

Before You File a Bug Report Please Confirm You Have Done The Following...

  • I have tried restarting my IDE and the issue persists.
  • I have updated to the latest version of the packages.
  • I have searched for related issues and found none that matched my issue.
  • I have read the FAQ and my problem is not listed.

Relevant Package

typescript-eslint

There are two bugs related to this issue: one meaningful and one mostly inconsequential.


1. Using extends in tseslint.config() creates global ignores

Playground Link

Reproduction with StackBlitz.

ESLint Config

import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';

export default tseslint.config(
  eslint.configs.recommended,
  tseslint.configs.recommended,
  {
    extends: [tseslint.configs.disableTypeChecked],
    ignores: ['**/*.ts', '**/*.tsx'],
  }
);

Expected Result

I expect that the ignores key only apply to the extend config, or at the very least not create a global ignores that affects the entire ESLint config.

In other words, I expect the resulting configuration array to be equivalent to this:

import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';

export default [
  eslint.configs.recommended,
  ...tseslint.configs.recommended,
  {
    ignores: ['**/*.ts', '**/*.tsx'],
    ...tseslint.configs.disableTypeChecked,
  }
];

Actual Result

If you look into the config inspector, the resulting config is the following:

> ...eslint/defaults
> eslint.configs.recommended
> ...tseslint.configs.recommended
> typescript-eslint/disable-type-checked
  - Ignore: ["**/*.ts", "**.tsx"]
  - ...tseslint.configs.disable-type-checked
> anonymous #10
  - Ignore files globally: ["**/**.ts", "**/*.tsx"]

In other words, the equivalent config array is

import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';

export default [
  eslint.configs.recommended,
  ...tseslint.configs.recommended,
  {
    ignores: ['**/*.ts', '**/*.tsx'],
    ...tseslint.configs.disableTypeChecked,
  },
  // Global ignores, ignores all .ts and .tsx files
  { ignores: ['**/*.ts', '**/*.tsx'] },
];

Extends will create a configuration with only the ignores key, which is parsed as a global ignores. Then, .ts and .tsx will not be linted.

This can be seen in the reproduction where src/index.ts is not linted as-is, while removing the extends config correctly allows it to be linted.


2. Using extends in tseslint.config() creates extraneous config

Playground Link

Reproduction with StackBlitz

ESLint Config

import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';

export default tseslint.config(
  eslint.configs.recommended,
  tseslint.configs.recommended,
  {
    extends: [tseslint.configs.disableTypeChecked],
    files: ['file'],
    ignores: ['ignored'],
    name: 'my-config',
  }
);

Expected Result

Per ESLint’s documentation (Debug your Configuration#Print a File’s Calculated Configuration), "You won’t see any entries for files, ignores, or name, because those are only used in calculating the final configuration and so do not appear in the result[ing configuration]."

I expect that if there are no meaningful keys for configuration and I only want to extend those configs with those keys, it should not create an unnecessary configuration file, and only updates the configs accordingly.

The ESLint configuration array should look like:

import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';

export default [
  eslint.configs.recommended,
  ...tseslint.configs.recommended,
  {
    files: ['file'],
    ignores: ['ignored'],
    name: 'my-config',
    ...tseslint.configs.disableTypeChecked,
  }
];

Actual Result

If you look into the config inspector, the resulting config is the following:

> ...eslint/defaults
> eslint.configs.recommended
> ...tseslint.configs.recommended
> my-config_typescript-eslint/disable-type-checked
  - Applies to files matching: ["file"]
  - Ignore: ["ignored"]
  - ...tseslint.configs.disable-type-checked
> my-config
  - Applies to files matching: ["file"]
  - Ignore: ["ignored"]

Or equivalently

import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';

export default [
  eslint.configs.recommended,
  ...tseslint.configs.recommended,
  {
    name: "my-config_typescript-eslint/disable-type-checked",
    files: ["file"],
    ignore: ["ignored"],
    ...tseslint.configs.disableTypeChecked,
  },
  // This config doesn't do anything
  { 
    name: "my-config",
    files: ["file"],
    ignore: ["ignored"],
  },
];

The final config in the config array named my-config doesn't do anything and is unnecessary, and may make debugging harder in more complex ESLint configs.


Versions

package version
@typescript-eslint 8.22.0
TypeScript 5.7.3
ESLint 9.19.0
@jeremy-code jeremy-code added bug Something isn't working triage Waiting for team members to take a look labels Feb 1, 2025
@jeremy-code jeremy-code changed the title Bug: <short description of the issue> Bug: config-helper.ts has unexpected behavior when base config contains only meta keys Feb 1, 2025
@bradzacher bradzacher added accepting prs Go ahead, send a pull request that resolves this issue package: typescript-eslint Issues related to the typescript-eslint package and removed triage Waiting for team members to take a look labels Feb 5, 2025
@jeremy-code
Copy link
Contributor Author

@bradzacher To clarify, there is already a PR that should close this issue: #10755 -- unless there is an issue with that PR?

@kirkwaiblinger
Copy link
Member

@jeremy-code Yep! We just use the "accepting prs" label to avoid spending time reviewing code that hasn't been discussed and agreed to. This issue, and therefore your PR, has been agreed to, so you're doing everything right! 👍 Someone will review the PR when we have bandwidth. The queue is pretty long right now 🙃

@github-actions github-actions bot added the locked due to age Please open a new issue if you'd like to say more. See https://typescript-eslint.io/contributing. label Apr 23, 2025
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 23, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
accepting prs Go ahead, send a pull request that resolves this issue bug Something isn't working locked due to age Please open a new issue if you'd like to say more. See https://typescript-eslint.io/contributing. package: typescript-eslint Issues related to the typescript-eslint package
Projects
None yet
3 participants