diff --git a/docs/usage.md b/docs/usage.md index c2fc351..b299081 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -192,6 +192,7 @@ export default config({ ### カスタム設定 ビルダー関数の第二引数には、カスタム設定の配列を与えることができます。プロジェクト固有の設定はここに追加するのがおすすめです。 +[typescript-eslint のユーティリティ](https://typescript-eslint.io/packages/typescript-eslint#config)をラップしているため、`extends` が利用できます。 ```javascript import config from '@hatena/eslint-config-hatena/flat'; @@ -200,6 +201,7 @@ import globals from 'globals'; export default config({}, [ { files: ['src/**/*.js'], + extends: [somePlugin.recommended], languageOptions: { globals: { ...globals.es2021, diff --git a/lib/config/index.js b/lib/config/index.js index 16e6d99..e820bb6 100644 --- a/lib/config/index.js +++ b/lib/config/index.js @@ -31,8 +31,8 @@ const rules = require('../rules/index.js'); /** * ESLint の設定を作る * @param {ConfigOptions} [options] オプション - * @param {readonly import('eslint').Linter.Config[]} [configs] カスタム設定の配列 - * @returns {import('eslint').Linter.Config[]} 設定の配列 + * @param {readonly import('typescript-eslint').ConfigWithExtends[]} [configs] カスタム設定の配列 + * @returns {import('typescript-eslint').Config} 設定の配列 */ function config(options, configs) { const tsProject = options?.tsProject ?? true; @@ -41,11 +41,11 @@ function config(options, configs) { const react = options?.react ?? false; const prettier = options?.prettier ?? true; - return [ + return tsEslint.config( // # Linter 自体の設定 { plugins: { - '@typescript-eslint': /** @type {import('eslint').ESLint.Plugin} */ (tsEslint.plugin), + '@typescript-eslint': tsEslint.plugin, // eslint-plugin-import v2.29.1時点ではESLint v9に対応していないため、互換性ユーティリティを通す。 'import': compat.fixupPluginRules(importPlugin), 'react': reactPlugin, @@ -82,7 +82,7 @@ function config(options, configs) { files: ['**/*.{ts,tsx,cts,mts}'], languageOptions: { sourceType: 'module', - parser: /** @type {import('eslint').Linter.Parser} */ (tsEslint.parser), + parser: tsEslint.parser, parserOptions: { ...(tsProjectService ? { projectService: tsProjectService } : tsProject ? { project: tsProject } : {}), tsconfigRootDir, @@ -93,41 +93,38 @@ function config(options, configs) { }, }, // # ルール設定 - ...map({ files: ['**/*.{js,jsx,cjs,mjs}', '**/*.{ts,tsx,cts,mts}'] }, [ - { rules: jsPlugin.configs.recommended.rules }, - { rules: importPlugin.configs.recommended.rules }, - { rules: rules.javascript }, - ...(react - ? [ - { rules: reactPlugin.configs.recommended.rules }, - { rules: reactPlugin.configs['jsx-runtime'].rules }, - { rules: reactHooksPlugin.configs.recommended.rules }, - { rules: rules.react }, - ] - : []), - ]), - ...map({ files: ['**/*.{ts,tsx,cts,mts}'] }, [ - // languageOptions なども含まれるが上で設定しているものと重複するので, ここでは rules のみに絞る - ...tsEslint.configs.recommendedTypeChecked.flatMap((config) => - config.rules ? [{ rules: /** @type {import('eslint').Linter.RulesRecord} */ (config.rules) }] : [], - ), - { rules: importPlugin.configs.typescript.rules }, - { rules: rules.typescript }, - ]), + { + files: ['**/*.{js,jsx,cjs,mjs}', '**/*.{ts,tsx,cts,mts}'], + extends: [{ rules: jsPlugin.configs.recommended.rules }, { rules: importPlugin.configs.recommended.rules }], + rules: rules.javascript, + }, + ...(react + ? [ + { + files: ['**/*.{js,jsx,cjs,mjs}', '**/*.{ts,tsx,cts,mts}'], + extends: [ + { rules: reactPlugin.configs.recommended.rules }, + { rules: reactPlugin.configs['jsx-runtime'].rules }, + { rules: reactHooksPlugin.configs.recommended.rules }, + ], + rules: rules.react, + }, + ] + : []), + { + files: ['**/*.{ts,tsx,cts,mts}'], + extends: [ + // recommendedTypeChecked には languageOptions なども含まれるが, 上で設定しているものと重複するのでここでは rules のみに絞る + ...tsEslint.configs.recommendedTypeChecked.flatMap((config) => (config.rules ? [{ rules: config.rules }] : [])), + { rules: importPlugin.configs.typescript.rules }, + ], + rules: rules.typescript, + }, // # カスタム設定 ...(configs ?? []), // # フォーマットに関するルールを無効化 ...(prettier ? [{ rules: prettierConfig.rules }] : []), - ]; -} - -/** - * @param {import('eslint').Linter.Config} base - * @param {readonly import('eslint').Linter.Config[]} configs - * @returns {import('eslint').Linter.Config[]} - */ -function map(base, configs) { - return configs.map((config) => ({ ...base, ...config })); + ); } module.exports = config;