diff --git a/eslint.config.js b/eslint.config.js index 5b6129a297..ae22ef071f 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -7,6 +7,9 @@ export default antfu( 'fixtures', '_fixtures', ], + // typescript: { + // tsconfigPath: 'tsconfig.json', + // }, }, { files: ['src/**/*.ts'], diff --git a/src/configs/typescript.ts b/src/configs/typescript.ts index 9c3d9d90ab..04ae6232d2 100644 --- a/src/configs/typescript.ts +++ b/src/configs/typescript.ts @@ -3,17 +3,41 @@ import type { FlatESLintConfigItem } from 'eslint-define-config' import { GLOB_TS, GLOB_TSX } from '../globs' import { parserTs, pluginAntfu, pluginImport, pluginTs } from '../plugins' import { OFF } from '../flags' -import type { OptionsComponentExts, OptionsOverrides, OptionsTypeScriptWithTypes } from '../types' +import type { OptionsComponentExts, OptionsOverrides, OptionsTypeScriptParserOptions, OptionsTypeScriptWithTypes } from '../types' import { renameRules } from '../utils' export function typescript( - options?: OptionsComponentExts & OptionsOverrides, + options?: OptionsComponentExts & OptionsOverrides & OptionsTypeScriptWithTypes & OptionsTypeScriptParserOptions, ): FlatESLintConfigItem[] { const { componentExts = [], overrides = {}, + parserOptions = {}, + tsconfigPath, } = options ?? {} + const typeAwareRules: FlatESLintConfigItem['rules'] = { + 'dot-notation': OFF, + 'no-implied-eval': OFF, + 'no-throw-literal': OFF, + 'ts/await-thenable': 'error', + 'ts/dot-notation': ['error', { allowKeywords: true }], + 'ts/no-floating-promises': 'error', + 'ts/no-for-in-array': 'error', + 'ts/no-implied-eval': 'error', + 'ts/no-misused-promises': 'error', + 'ts/no-throw-literal': 'error', + 'ts/no-unnecessary-type-assertion': 'error', + 'ts/no-unsafe-argument': 'error', + 'ts/no-unsafe-assignment': 'error', + 'ts/no-unsafe-call': 'error', + 'ts/no-unsafe-member-access': 'error', + 'ts/no-unsafe-return': 'error', + 'ts/restrict-plus-operands': 'error', + 'ts/restrict-template-expressions': 'error', + 'ts/unbound-method': 'error', + } + return [ { // Install the plugins without globs, so they can be configured separately. @@ -33,6 +57,13 @@ export function typescript( parser: parserTs, parserOptions: { sourceType: 'module', + ...tsconfigPath + ? { + project: [tsconfigPath], + tsconfigRootDir: process.cwd(), + } + : {}, + ...parserOptions as any, }, }, rules: { @@ -78,6 +109,7 @@ export function typescript( 'ts/prefer-ts-expect-error': 'error', 'ts/triple-slash-reference': OFF, + ...tsconfigPath ? typeAwareRules : {}, ...overrides, }, }, @@ -104,54 +136,3 @@ export function typescript( }, ] } - -export function typescriptWithTypes( - options: OptionsTypeScriptWithTypes & OptionsComponentExts & OptionsOverrides, -): FlatESLintConfigItem[] { - const { - componentExts = [], - tsconfigPath, - tsconfigRootDir = process.cwd(), - overrides = {}, - } = options - - return [ - { - files: [ - GLOB_TS, - GLOB_TSX, - ...componentExts.map(ext => `**/*.${ext}`), - '!**/*.md/*.*', - ], - languageOptions: { - parser: parserTs, - parserOptions: { - project: [tsconfigPath], - tsconfigRootDir, - }, - }, - rules: { - 'dot-notation': OFF, - 'no-implied-eval': OFF, - 'no-throw-literal': OFF, - 'ts/await-thenable': 'error', - 'ts/dot-notation': ['error', { allowKeywords: true }], - 'ts/no-floating-promises': 'error', - 'ts/no-for-in-array': 'error', - 'ts/no-implied-eval': 'error', - 'ts/no-misused-promises': 'error', - 'ts/no-throw-literal': 'error', - 'ts/no-unnecessary-type-assertion': 'error', - 'ts/no-unsafe-argument': 'error', - 'ts/no-unsafe-assignment': 'error', - 'ts/no-unsafe-call': 'error', - 'ts/no-unsafe-member-access': 'error', - 'ts/no-unsafe-return': 'error', - 'ts/restrict-plus-operands': 'error', - 'ts/restrict-template-expressions': 'error', - 'ts/unbound-method': 'error', - ...overrides, - }, - }, - ] -} diff --git a/src/factory.ts b/src/factory.ts index ca015f151b..9611ea22c2 100644 --- a/src/factory.ts +++ b/src/factory.ts @@ -17,7 +17,6 @@ import { stylistic, test, typescript, - typescriptWithTypes, unicorn, vue, yaml, @@ -94,17 +93,12 @@ export function antfu(options: OptionsConfig & FlatESLintConfigItem = {}, ...use if (enableTypeScript) { configs.push(typescript({ + ...typeof enableTypeScript !== 'boolean' + ? enableTypeScript + : {}, componentExts, overrides: overrides.typescript, })) - - if (typeof enableTypeScript !== 'boolean') { - configs.push(typescriptWithTypes({ - ...enableTypeScript, - componentExts, - overrides: overrides.typescriptWithTypes, - })) - } } if (enableStylistic) diff --git a/src/types.ts b/src/types.ts index 7c9ce949ba..49a496443e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,5 +1,6 @@ import type { FlatGitignoreOptions } from 'eslint-config-flat-gitignore' import type { FlatESLintConfigItem } from 'eslint-define-config' +import type { ParserOptions } from '@typescript-eslint/parser' export interface OptionsComponentExts { /** @@ -11,9 +12,19 @@ export interface OptionsComponentExts { componentExts?: string[] } +export interface OptionsTypeScriptParserOptions { + /** + * Additional parser options for TypeScript. + */ + parserOptions?: Partial +} + export interface OptionsTypeScriptWithTypes { - tsconfigPath: string - tsconfigRootDir?: string + /** + * When this options is provided, type aware rules will be enabled. + * @see https://typescript-eslint.io/linting/typed-linting/ + */ + tsconfigPath?: string } export interface OptionsHasTypeScript { @@ -106,7 +117,6 @@ export interface OptionsConfig { overrides?: { javascript?: FlatESLintConfigItem['rules'] typescript?: FlatESLintConfigItem['rules'] - typescriptWithTypes?: FlatESLintConfigItem['rules'] test?: FlatESLintConfigItem['rules'] vue?: FlatESLintConfigItem['rules'] jsonc?: FlatESLintConfigItem['rules']