🌐 AI搜索 & 代理 主页
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions packages/typescript-eslint/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,18 @@
"targets": {
"lint": {
"command": "eslint"
},
"typecheck": {
"outputs": [
"{workspaceRoot}/dist",
"{projectRoot}/dist"
]
},
"test": {
"dependsOn": [
"^build",
"typecheck"
]
}
}
}
Expand Down
25 changes: 25 additions & 0 deletions packages/typescript-eslint/src/compatibility-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* This file contains types that are intentionally wide/inaccurate, that exist
* for the purpose of satisfying both `defineConfig()` and `tseslint.config()`.
* See https://github.com/typescript-eslint/typescript-eslint/issues/10899
*/

export interface CompatibleParser {
parseForESLint(text: string): {
ast: unknown;
scopeManager: unknown;
};
}

export interface CompatibleConfig {
name?: string;
rules?: object;
}

export type CompatibleConfigArray = CompatibleConfig[];

export interface CompatiblePlugin {
meta: {
name: string;
};
}
66 changes: 44 additions & 22 deletions packages/typescript-eslint/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
// see the comment in config-helper.ts for why this doesn't use /ts-eslint
import type { TSESLint } from '@typescript-eslint/utils';
import type { FlatConfig } from '@typescript-eslint/utils/ts-eslint';

import pluginBase from '@typescript-eslint/eslint-plugin';
import rawPlugin from '@typescript-eslint/eslint-plugin/use-at-your-own-risk/raw-plugin';
import { addCandidateTSConfigRootDir } from '@typescript-eslint/typescript-estree';

import type {
CompatibleConfig,
CompatibleConfigArray,
CompatibleParser,
CompatiblePlugin,
} from './compatibility-types';

import { config } from './config-helper';
import { getTSConfigRootDirFromStack } from './getTSConfigRootDirFromStack';

export const parser: TSESLint.FlatConfig.Parser = rawPlugin.parser;
export const parser: CompatibleParser =
rawPlugin.parser as CompatibleParser satisfies FlatConfig.Parser;

/*
we could build a plugin object here without the `configs` key - but if we do
Expand All @@ -33,96 +42,109 @@ use our new package); however legacy configs consumed via `@eslint/eslintrc`
would never be able to satisfy this constraint and thus users would be blocked
from using them.
*/
export const plugin: TSESLint.FlatConfig.Plugin = pluginBase as Omit<
typeof pluginBase,
'configs'
>;
export const plugin: CompatiblePlugin =
pluginBase satisfies FlatConfig.Plugins['string'];

export const configs = createConfigsGetters({
/**
* Enables each the rules provided as a part of typescript-eslint. Note that many rules are not applicable in all codebases, or are meant to be configured.
* @see {@link https://typescript-eslint.io/users/configs#all}
*/
all: rawPlugin.flatConfigs['flat/all'],
all: rawPlugin.flatConfigs['flat/all'] as CompatibleConfigArray,

/**
* A minimal ruleset that sets only the required parser and plugin options needed to run typescript-eslint.
* We don't recommend using this directly; instead, extend from an earlier recommended rule.
* @see {@link https://typescript-eslint.io/users/configs#base}
*/
base: rawPlugin.flatConfigs['flat/base'],
base: rawPlugin.flatConfigs['flat/base'] as CompatibleConfig,

/**
* A utility ruleset that will disable type-aware linting and all type-aware rules available in our project.
* @see {@link https://typescript-eslint.io/users/configs#disable-type-checked}
*/
disableTypeChecked: rawPlugin.flatConfigs['flat/disable-type-checked'],
disableTypeChecked: rawPlugin.flatConfigs[
'flat/disable-type-checked'
] as CompatibleConfig,

/**
* This is a compatibility ruleset that:
* - disables rules from eslint:recommended which are already handled by TypeScript.
* - enables rules that make sense due to TS's typechecking / transpilation.
* @see {@link https://typescript-eslint.io/users/configs/#eslint-recommended}
*/
eslintRecommended: rawPlugin.flatConfigs['flat/eslint-recommended'],
eslintRecommended: rawPlugin.flatConfigs[
'flat/eslint-recommended'
] as CompatibleConfig,

/**
* Recommended rules for code correctness that you can drop in without additional configuration.
* @see {@link https://typescript-eslint.io/users/configs#recommended}
*/
recommended: rawPlugin.flatConfigs['flat/recommended'],
recommended: rawPlugin.flatConfigs[
'flat/recommended'
] as CompatibleConfigArray,

/**
* Contains all of `recommended` along with additional recommended rules that require type information.
* @see {@link https://typescript-eslint.io/users/configs#recommended-type-checked}
*/
recommendedTypeChecked:
rawPlugin.flatConfigs['flat/recommended-type-checked'],
recommendedTypeChecked: rawPlugin.flatConfigs[
'flat/recommended-type-checked'
] as CompatibleConfigArray,

/**
* A version of `recommended` that only contains type-checked rules and disables of any corresponding core ESLint rules.
* @see {@link https://typescript-eslint.io/users/configs#recommended-type-checked-only}
*/
recommendedTypeCheckedOnly:
rawPlugin.flatConfigs['flat/recommended-type-checked-only'],
recommendedTypeCheckedOnly: rawPlugin.flatConfigs[
'flat/recommended-type-checked-only'
] as CompatibleConfigArray,

/**
* Contains all of `recommended`, as well as additional strict rules that can also catch bugs.
* @see {@link https://typescript-eslint.io/users/configs#strict}
*/
strict: rawPlugin.flatConfigs['flat/strict'],
strict: rawPlugin.flatConfigs['flat/strict'] as CompatibleConfigArray,

/**
* Contains all of `recommended`, `recommended-type-checked`, and `strict`, along with additional strict rules that require type information.
* @see {@link https://typescript-eslint.io/users/configs#strict-type-checked}
*/
strictTypeChecked: rawPlugin.flatConfigs['flat/strict-type-checked'],
strictTypeChecked: rawPlugin.flatConfigs[
'flat/strict-type-checked'
] as CompatibleConfigArray,

/**
* A version of `strict` that only contains type-checked rules and disables of any corresponding core ESLint rules.
* @see {@link https://typescript-eslint.io/users/configs#strict-type-checked-only}
*/
strictTypeCheckedOnly: rawPlugin.flatConfigs['flat/strict-type-checked-only'],
strictTypeCheckedOnly: rawPlugin.flatConfigs[
'flat/strict-type-checked-only'
] as CompatibleConfigArray,

/**
* Rules considered to be best practice for modern TypeScript codebases, but that do not impact program logic.
* @see {@link https://typescript-eslint.io/users/configs#stylistic}
*/
stylistic: rawPlugin.flatConfigs['flat/stylistic'],
stylistic: rawPlugin.flatConfigs['flat/stylistic'] as CompatibleConfigArray,

/**
* Contains all of `stylistic`, along with additional stylistic rules that require type information.
* @see {@link https://typescript-eslint.io/users/configs#stylistic-type-checked}
*/
stylisticTypeChecked: rawPlugin.flatConfigs['flat/stylistic-type-checked'],
stylisticTypeChecked: rawPlugin.flatConfigs[
'flat/stylistic-type-checked'
] as CompatibleConfigArray,

/**
* A version of `stylistic` that only contains type-checked rules and disables of any corresponding core ESLint rules.
* @see {@link https://typescript-eslint.io/users/configs#stylistic-type-checked-only}
*/
stylisticTypeCheckedOnly:
rawPlugin.flatConfigs['flat/stylistic-type-checked-only'],
});
stylisticTypeCheckedOnly: rawPlugin.flatConfigs[
'flat/stylistic-type-checked-only'
] as CompatibleConfigArray,
}) satisfies Record<string, FlatConfig.Config | FlatConfig.ConfigArray>;

function createConfigsGetters<T extends object>(values: T): T {
const configs = {};
Expand Down
49 changes: 49 additions & 0 deletions packages/typescript-eslint/tests/type-compatibility.test-d.ts
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is test-d.ts run by vitest? TIL

Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { defineConfig } from 'eslint/config';

import tseslint from '../src/index';

describe('test for compatibility with config helpers', () => {
test('exported plugin is compatible with tseslint.config()', () => {
tseslint.config({
plugins: {
'@typescript-eslint': tseslint.plugin,
},
});
});

test('exported plugin is compatible with defineConfig()', () => {
defineConfig({
plugins: {
'@typescript-eslint': tseslint.plugin,
},
});
});

test('exported parser is compatible with tseslint.config()', () => {
tseslint.config({
languageOptions: {
parser: tseslint.parser,
},
});
});

test('exported parser is compatible with defineConfig()', () => {
defineConfig({
languageOptions: {
parser: tseslint.parser,
},
});
});

test('exported configs are compatible with tseslint.config()', () => {
tseslint.config(tseslint.configs.recommendedTypeChecked);
tseslint.config(tseslint.configs.strict);
tseslint.config(tseslint.configs.eslintRecommended);
});

test('exported configs are compatible with defineConfig()', () => {
defineConfig(tseslint.configs.recommendedTypeChecked);
defineConfig(tseslint.configs.strict);
defineConfig(tseslint.configs.eslintRecommended);
});
});
4 changes: 4 additions & 0 deletions packages/typescript-eslint/vitest.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ const vitestConfig = mergeConfig(
dir: path.join(import.meta.dirname, 'tests'),
name: packageJson.name,
root: import.meta.dirname,
typecheck: {
enabled: true,
tsconfig: path.join(import.meta.dirname, 'tsconfig.spec.json'),
},
},
}),
);
Expand Down
Loading