@itcode-dev/eslint-config
itcode.dev ์ ์ญ ESLint ์ค์
# npm
npm add -D @itcode-dev/eslint-config
# yarn
yarn add -D @itcode-dev/eslint-config
# yarn berry
yarn add -D @itcode-dev/eslint-config eslint-plugin-better-tailwindcss eslint-plugin-import eslint-plugin-jest @next/eslint-plugin-next eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-sort-keys-fix @tanstack/eslint-plugin-query typescript-eslint eslint-plugin-unused-imports
# pnpm
pnpm add -D @itcode-dev/eslint-config
import itcodeConfig from '@itcode-dev/eslint-config'
// eslint.config.js
module . expors = [
itcode . configs . baseConfig
]
import baseConfig from '@itcode-dev/eslint-config/base'
// eslint.config.js
module . expors = [
baseConfig
]
import type { Linter } from 'eslint' ;
export default {
// Override or add rules here
rules : {
// ๊ฐ๋ฅํ๋ค๋ฉด, ์ ๋ก์ฐ ๋ฉ์๋๋ ์ค๊ดํธ๋ฅผ ๋ฌถ์ง ์๊ณ ๋ฐํํจ
'arrow-body-style' : [
'error' ,
'as-needed'
] ,
// ๊ตฌ๋ฌธ ์ค๊ดํธ๋ฅผ ๋ฐ๋์ ๋ช
์ํ๋๋ก ๊ฐ์
curly : 'error' ,
// switch์ default ๊ตฌ๋ฌธ์ด ๋ฐ๋์ ์ตํ๋จ์ ์์นํ๋๋ก ๊ฐ์
'default-case-last' : 'error' ,
// ๊ธฐ๋ณธ๊ฐ์ด ๋ช
์๋ ํ๋ผ๋ฏธํฐ๋ ๊ฐ์ฅ ๋ง์ง๋ง์ ์์นํ๋๋ก ๊ฐ์
'default-param-last' : 'error' ,
// === ๋น๊ต ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ๋๋ก ๊ฐ์
eqeqeq : 'error' ,
// alert(๊ธ์ง)
'no-alert' : 'error' ,
// ๋ฐ๋ณต๋ฌธ์์์ ๋ฐ๋ณต๋ฌธ์์์ ๋ฐ๋ณต๋ฌธ์์์ await ํ์ฉ
'no-await-in-loop' : 'off' ,
// console ์ฌ์ฉ ๋ฐฉ์ง, ํ์ํ๋ค๋ฉด ๋ผ์ธ๋ณ ์ต์
๋นํ์ฑํ๋ก ๋์. ๋จ, warn๊ณผ error๋ ํ์ฉ
'no-console' : [
'error' ,
{
allow : [
'warn' ,
'error'
]
}
] ,
// ์กฐ๊ฑด๋ฌธ์์์ ๋ถํ์ํ return ์ฌ์ฉ ๋ฐฉ์ง
'no-else-return' : 'error' ,
// ๋น ๋ฉ์๋ ๋ฐฉ์ง
'no-empty-function' : 'error' ,
// null ๋น๊ต์ eq ์ฐ์ฐ์ ์ฌ์ฉ ๋ฐฉ์ง
'no-eq-null' : 'error' ,
// eval is evil
'no-eval' : 'error' ,
// ๋ถํ์ํ bool ์บ์คํ
๋ฐฉ์ง
'no-extra-boolean-cast' : 'error' ,
// ๋ํดํ ์บ์คํ
์ฐ์ฐ ๋ฐฉ์ง
'no-implicit-coercion' : 'error' ,
// eval ์ ์ฌ ๋ฉ์๋ ์ฌ์ฉ ๋ฐฉ์ง
'no-implied-eval' : 'error' ,
// ์ฝ๋ ๋์ค์ ์ธ๋ผ์ธ ์ฃผ์ ๋ฐฉ์ง
'no-inline-comments' : 'error' ,
// __iterator__ ํ๋กํผํฐ ์ฌ์ฉ ๋ฐฉ์ง
'no-iterator' : 'error' ,
// ๋ฌด์๋ฏธํ ๋ธ๋ก๋ฌธ ๋ฐฉ์ง
'no-lone-blocks' : 'error' ,
// ๋ถํ์ํ ์กฐ๊ฑด๋ฌธ ์ค์ฒฉ ๋ฐฉ์ง
'no-lonely-if' : 'error' ,
// ํ ๋น์ด๋ ๋น๊ต๊ฐ ์๋ ๋จ๋
new ์ฐ์ฐ์ ๋ฐฉ์ง
'no-new' : 'error' ,
// Function์ ํ์ฉํ ๋ฉ์๋ ์์ฑ ๋ฐฉ์ง
'no-new-func' : 'error' ,
// ๋ถํ์ํ ๋ํ์ new ์ฐ์ฐ์ ๋ฐฉ์ง
'no-new-wrappers' : 'error' ,
// ๋ถํ์ํ Object ์์ฑ์ ๋ฐฉ์ง
'no-object-constructor' : 'error' ,
// 8์ง์ ์ด์ค์ผ์ดํ ๋ฐฉ์ง
'no-octal-escape' : 'error' ,
// ํ๋ผ๋ฏธํฐ ์ฌํ ๋น ๋ฐฉ์ง
'no-param-reassign' : 'error' ,
// __proto__ ํ๋กํผํฐ ์ฌ์ฉ ๋ฐฉ์ง
'no-proto' : 'error' ,
// javascript:console.log(์ฌ์ฉ๊ธ์ง)
'no-script-url' : 'error' ,
// ์์ ์ค์ฝํ์์ ์ฌ์ฉ๋ ๋ณ์๋ช
์ ํ์ ์ค์ฝํ์์ ์ฌ์ฉ ๋ฐฉ์ง
'no-shadow' : 'error' ,
// ๋ฆฌํฐ๋ด ์์ธ์ฒ๋ฆฌ ๋ฐฉ์ง
'no-throw-literal' : 'error' ,
// ํ ๋น๋์ง ์์ ์ด๊ธฐ ๋ณ์์ undefined ํ ๋น ๋ฐฉ์ง
'no-undef-init' : 'error' ,
// ์ฌ์ฉํ์ง ์๋ ํํ ๋ฐฉ์ง
'no-unused-expressions' : 'error' ,
// ์ฌ์ฉํ์ง ์๋ ๋ณ์๋ช
๋ฐฉ์ง
'no-unused-vars' : 'error' ,
// ๋ถํ์ํ ๋ฉ์๋ call, bind ์ฌ์ฉ ๋ฐฉ์ง
'no-useless-call' : 'error' ,
// "๋ถํ์ํ" + "๋ฌธ์์ด" + "์ด์ด์ฐ๊ธฐ" + "๋ฐฉ์ง"
'no-useless-concat' : 'error' ,
// ๋ถํ์ํ return ๋ฐฉ์ง
'no-useless-return' : 'error' ,
// 'var' is banned by Developer
'no-var' : 'error' ,
// 'void' you too
'no-void' : 'error' ,
// ๊ฐ๊ฒฐํ ํ์ ํํ ๊ฐ์
'object-shorthand' : 'error' ,
// ์ถ์ฐ๊ฐ (์ถ์ฝํ ์ฐ์ฐ์ ๊ฐ์ ๋ผ๋ ๋ป)
'operator-assignment' : 'error' ,
// (์ ๋ก์ฐ ๋ฉ์๋) => ์ฌ์ฉ ๊ถ์ฅ
'prefer-arrow-callback' : 'error' ,
// const ์ฌ์ฉ ๊ถ์ฅ
'prefer-const' : 'error' ,
// { ๊ตฌ์กฐ, ํ๊ดด } = ํ์ ๊ฐ์
'prefer-destructuring' : 'error' ,
// ์ง์ ํจ์ ๋์ ** ์ฐ์ฐ์ ๊ฐ์
'prefer-exponentiation-operator' : 'error' ,
// `${string} ํ
ํ๋ฆฟ ๊ฐ์ `
'prefer-template' : 'error' ,
// await ์ง์์๋ฅผ ์ฌ์ฉํ์ง ์๋ ๋ฉ์๋์ asyncํ ๋ฐฉ์ง
'require-await' : 'error' ,
// ํค ์ ๋ ฌ ๊ฐ์
'sort-keys' : 'error' ,
// ๋ฐฉ์งํจ, ์๋ค ํํ์
yoda : 'error'
}
} satisfies Linter . Config ;
eslint-plugin-better-tailwindcss ์ค์
import pluginBetterTailwindcss from 'eslint-plugin-better-tailwindcss' ;
import type { Linter } from 'eslint' ;
export default {
plugins : { '@better-tailwindcss' : pluginBetterTailwindcss } ,
rules : {
// ์ผ๊ด๋ ํด๋์ค ์ ๋ ฌ ๊ฐ์
'@better-tailwindcss/enforce-consistent-class-order' : 'error' ,
// ์ผ๊ด๋ ํด๋์ค ๋ํ ๊ฐ์
'@better-tailwindcss/enforce-consistent-line-wrapping' : 'error' ,
// ์ผ๊ด๋ CSS ๋ณ์ ํธ์ถ ๋ฐฉ์ ๊ฐ์
'@better-tailwindcss/enforce-consistent-variable-syntax' : 'error' ,
// ์ถ๋ํ๋ ํด๋์ค ์คํ์ผ๋ง ๋ฐฉ์ง
'@better-tailwindcss/no-conflicting-classes' : 'error' ,
// ์ค๋ณต๋ ํด๋์ค ๋ฐฉ์ง
'@better-tailwindcss/no-duplicate-classes' : 'error' ,
// ๋ถํ์ ๊ณต๋ฐฑ ์ ๊ฑฐ
'@better-tailwindcss/no-unnecessary-whitespace' : 'error'
}
} satisfies Linter . Config ;
eslint-plugin-import ์ค์
import pluginImport from 'eslint-plugin-import' ;
import type { Linter } from 'eslint' ;
export default {
plugins : { '@import' : pluginImport } ,
rules : {
// ๊ธฐ๋ณธ ๊ฐ์ ธ์ค๊ธฐ ์ ํจ์ฑ ๊ฒ์ฆ
'@import/default' : 'error' ,
// export ์ ํจ์ฑ ๊ฒ์ฆ
'@import/export' : 'error' ,
// export๋ ๋ฐ๋์ ํ๋จ์ ์์น
'@import/exports-last' : 'error' ,
// import๋ ๋ฐ๋์ ์๋จ์ ์์น
'@import/first' : 'error' ,
// ๋ช
๋ช
๋ import๊ฐ ์ ํํ export ์ธ์ง ๊ฒ์ฆ
'@import/named' : 'error' ,
// namespace๊ฐ ์ค์ ๋ก export ๋๋์ง ๊ฒ์ฆ
'@import/namespace' : 'error' ,
// import ๊ตฌ๋ฌธ ๋ง์ง๋ง์ ๋ฐ๋์ ์ค๋ฐ๊ฟ
'@import/newline-after-import' : 'error' ,
// ์ ๋๊ฒฝ๋ก import ๋ฐฉ์ง
'@import/no-absolute-path' : 'error' ,
// deprecated import ๋ฐฉ์ง
'@import/no-deprecated' : 'error' ,
// ์ค๋ณต๋ import ๋ฐฉ์ง
'@import/no-duplicates' : 'error' ,
// ๋น import ๋ฐฉ์ง
'@import/no-empty-named-blocks' : 'error' ,
// ๊ธฐ๋ณธ import๋ ์ด๋ฆ๊ณผ ๋์ผํ๋๋ก ๊ฐ์
'@import/no-named-as-default' : 'error' ,
// ๊ธฐ๋ณธ export์์ ๊ฐ์ ์ด๋ฆ์ ์์ฑ ์ ๊ทผ ๋ฐฉ์ง
'@import/no-named-as-default-member' : 'error' ,
// ์ ๋ ฌ ๊ฐ์
'@import/order' : [
'error' ,
{
alphabetize : {
caseInsensitive : true ,
order : 'asc'
} ,
groups : [
'builtin' ,
'external' ,
'internal' ,
'parent' ,
'sibling' ,
'index' ,
'type' ,
'unknown'
] ,
named : true ,
'newlines-between' : 'always' ,
pathGroups : [ {
group : 'internal' ,
pattern : '@kapoo/**' ,
position : 'before'
} ] ,
pathGroupsExcludedImportTypes : [ 'builtin' ] ,
warnOnUnassignedImports : true
}
]
}
} satisfies Linter . Config ;
eslint-plugin-jest ์ค์
import pluginJest from 'eslint-plugin-jest' ;
import type { Linter } from 'eslint' ;
export default {
files : [
'**/*.spec.[jt]s?(x)' ,
'**/*.test.[jt]s?(x)'
] ,
languageOptions : { globals : pluginJest . environments . globals . globals } ,
plugins : { '@jest' : pluginJest } ,
rules : {
// ์ง์์ด๋ it์ผ๋ก ๊ฐ์ ํจ
'@jest/consistent-test-it' : [
'error' ,
{ fn : 'it' }
] ,
// ํ
์คํธ ๊ตฌ๋ฌธ์์ ์ด์ฐ์
๋๋ฝ ๋ฐฉ์ง
'@jest/expect-expect' : 'error' ,
// ๋ณ์นญ ๋ฉ์๋๊ฐ ์๋ ๊ณต์ ๋ฉ์๋ ์ฌ์ฉ ๊ฐ์
'@jest/no-alias-methods' : 'error' ,
// ํ
์คํธ ๊ตฌ๋ฌธ ์ฃผ์ ์ฒ๋ฆฌ ๋ฐฉ์ง
'@jest/no-commented-out-tests' : 'error' ,
// ์กฐ๊ฑด๋ถ ํธ์ถ ๋ฐฉ์ง
'@jest/no-conditional-expect' : 'error' ,
// ํผ๋์ค๋ฐ setTimeout ์ฌ์ฉ ๋ฐฉ์ง
'@jest/no-confusing-set-timeout' : 'error' ,
// deprecated ๋ฉ์๋ ์ฌ์ฉ ๋ฐฉ์ง
'@jest/no-deprecated-functions' : 'error' ,
// ๋นํ์ฑํ๋ ํ
์คํธ ์ฌ์ฉ ๋ฐฉ์ง
'@jest/no-disabled-tests' : 'error' ,
// ๋น๋๊ธฐ ํ
์คํธ์์ ์ฝ๋ฐฑ ์ฌ์ฉ ๋ฐฉ์ง
'@jest/no-done-callback' : 'error' ,
// ์ค๋ณต๋ ํ
์คํธ ํ
๋ฐฉ์ง
'@jest/no-duplicate-hooks' : 'error' ,
// export ๋ฐฉ์ง๋ฅผ ํตํด ์ด ๊ทธ์ง๊ฐ์ ์ปดํฌ๋ํธ์ ํ
์คํธ ์ ์ถ ๋ฐฉ์ง
'@jest/no-export' : 'error' ,
// ํ
์คํธ์ only ์ง์์ ์ฌ์ฉ ๋ฐฉ์ง
'@jest/no-focused-tests' : 'error' ,
// ๋๋ช
์ดํ
์คํธ ๋ฐฉ์ง
'@jest/no-identical-title' : 'error' ,
// ์ค๋
์ท์์ ๋ฆฌํฐ๋ด ๋ณ์ ์ฌ์ฉ ๋ฐฉ์ง
'@jest/no-interpolation-in-snapshots' : 'error' ,
// jasmine ์ ์ญ ๋ณ์ ์ ์ธ ๋ฐฉ์ง
'@jest/no-jasmine-globals' : 'error' ,
// mock ์ง์ import ๋ฐฉ์ง
'@jest/no-mocks-import' : 'error' ,
// ๋จ๋
expect ๋ฐฉ์ง
'@jest/no-standalone-expect' : 'error' ,
// ๋ถํ์ํ ํ
์คํธ prefix ๋ฐฉ์ง
'@jest/no-test-prefixes' : 'error' ,
// ํ
์คํธ๋ ์๋ฌด๊ฒ๋ ๋ฐํํ์ง ์์
'@jest/no-test-return-statement' : 'error' ,
// mock์ ๋ฐ๋์ ํ์
์ ์ง์ ํด์ผํจ (JS์์ ๋นํ์ฑํ ํ์)
'@jest/no-untyped-mock-factory' : 'error' ,
// ๊ฐ ๋ธ๋ก ์ฃผ์๋ก ๊ฒฐ๊ณ ํ์ฑ
'@jest/padding-around-all' : 'error' ,
// mock.calls ๋์ toHaveBeenCalledWith() ์ฌ์ฉ
'@jest/prefer-called-with' : 'error' ,
// ๋ด์ฅ๋ ๋น๊ต ๋งค์ฒ ์ฌ์ฉ
'@jest/prefer-comparison-matcher' : 'error' ,
// for๋ฌธ์ ์ง์ ๊ตฌ์ฑํ๋ ๊ฒ๋ณด๋ค .each ์ฌ์ฉ
'@jest/prefer-each' : 'error' ,
// ๋ด์ฅ ๋๋ฑ ๋น๊ต ๋งค์ฒ ์ฌ์ฉ
'@jest/prefer-equality-matcher' : 'error' ,
// Promise๋ฅผ ํตํ ๋น๋๊ธฐ ๋น๊ต๋ resolves ์ฌ์ฉ
'@jest/prefer-expect-resolves' : 'error' ,
// ํ
์ ๋ ฌ
'@jest/prefer-hooks-in-order' : 'error' ,
// jest.mocked ์ฌ์ฉํ์ฌ mocking ๊ฐ์
'@jest/prefer-jest-mocked' : 'error' ,
// ๊ฐ๊ฒฐํ Promise mock ์ ์ธ ๊ฐ์
'@jest/prefer-mock-promise-shorthand' : 'error' ,
// snapshot ํํธ ๊ฐ์
'@jest/prefer-snapshot-hint' : 'error' ,
// ์๊ฒฉํ ๋น๊ต์ธ toStrictEqual ์ฌ์ฉ
'@jest/prefer-strict-equal' : 'error' ,
// ์์๊ฐ ๋น๊ต ์ toBe ๊ธฐ๋ฐ ๋ฉ์๋ ์ฌ์ฉ
'@jest/prefer-to-be' : 'error' ,
// ํฌํจ ์ฌ๋ถ ๋น๊ต ์ toContain ๋ฉ์๋ ์ฌ์ฉ
'@jest/prefer-to-contain' : 'error' ,
// ๊ธธ์ด ๋น๊ต ์ toHaveLength ๋ฉ์๋ ์ฌ์ฉ
'@jest/prefer-to-have-length' : 'error' ,
// ๋น ํ
์คํธ ์ผ์ด์ค์ธ todo ์ฌ์ฉ
'@jest/prefer-todo' : 'error' ,
// throws ์ ์ ์๋ฏธํ ๋ฉ์์ง ์ง์ ๊ฐ์
'@jest/require-to-throw-message' : 'error' ,
// ์ ํจํ describe ์ฝ๋ฐฑ ๋ฉ์๋ ์ฌ์ฉ
'@jest/valid-describe-callback' : 'error' ,
// expect๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌ๋๋๋ก ๊ฐ์
'@jest/valid-expect' : 'error' ,
// Promise๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌ๋๋๋ก ๊ฐ์
'@jest/valid-expect-in-promise' : 'error' ,
// ํ
์คํธ๊ฐ ์ฌ๋ฐ๋ฅธ ํ์ดํ์ ๊ฐ๋๋ก ๊ฐ์
'@jest/valid-title' : 'error'
}
} satisfies Linter . Config ;
eslint-plugin-next ์ค์
import pluginNext from '@next/eslint-plugin-next' ;
import type { Linter } from 'eslint' ;
export default {
plugins : { '@next' : pluginNext } ,
rules : {
// font-display ์ค์ ์ ํตํ ํฐํธ ๋ก๋ ์ ์ด ๋ฐฉ์ ๊ฐ์
'@next/google-font-display' : 'error' ,
// Google Fonts pre-load ๊ฐ์
'@next/google-font-preconnect' : 'error' ,
// ์ธ๋ผ์ธ script id ๊ฐ์
'@next/inline-script-id' : 'error' ,
// GA ์ ์ฉ ์ next/script ์ฌ์ฉ ๊ฐ์
'@next/next-script-for-ga' : 'error' ,
// ๋ชจ๋ ๋ณ์ ํ ๋น ๋ฐฉ์ง
'@next/no-assign-module-variable' : 'error' ,
// ๋น๋๊ธฐ CSR ์ปดํฌ๋ํธ ๋ฐฉ์ง
'@next/no-async-client-component' : 'error' ,
// beforeInteractive ์คํฌ๋ฆฝํธ๋ head ์์ ์์นํ๋๋ก ๊ฐ์
'@next/no-before-interactive-script-outside-document' : 'error' ,
// style ํ๊ทธ ๋ฐฉ์ง
'@next/no-css-tags' : 'error' ,
// document ์ปดํฌ๋ํธ import ๋ฐฉ์ง
'@next/no-document-import-in-page' : 'error' ,
// ํค๋ ์ค๋ณต ๋ฐฉ์ง
'@next/no-duplicate-head' : 'error' ,
// head ๋์ next/head ์ฌ์ฉ ๊ฐ์
'@next/no-head-element' : 'error' ,
// _document์์ next/head ์ฌ์ฉ ๋ฐฉ์ง
'@next/no-head-import-in-document' : 'error' ,
// next/link ์ฌ์ฉ ๊ฐ์
'@next/no-html-link-for-pages' : 'error' ,
// next/image ์ฌ์ฉ ๊ฐ์
'@next/no-img-element' : 'error' ,
// ํ์ด์ง ๋ด ํฐํธ ์ค์ ๋ฐฉ์ง
'@next/no-page-custom-font' : 'error' ,
// next/head ๋ด์ next/script ์ปดํฌ๋ํธ ์ฌ์ฉ ๋ฐฉ์ง
'@next/no-script-component-in-head' : 'error' ,
// _document ๋ด์ styled-jsx ์ ์ธ ๋ฐฉ์ง
'@next/no-styled-jsx-in-document' : 'error' ,
// ๋น๋๊ธฐ script ๊ฐ์
'@next/no-sync-scripts' : 'error' ,
// ํ์ด์ง๋ณ title์ next/head๋ฅผ ์ฌ์ฉํ๋๋ก ๊ฐ์
'@next/no-title-in-document-head' : 'error' ,
// ์คํ ๋ฐฉ์ง
'@next/no-typos' : 'error' ,
// ๋ถํ์ํ Polyfill.io ์คํฌ๋ฆฝํธ ๋ฐฉ์ง
'@next/no-unwanted-polyfillio' : 'error'
}
} satisfies Linter . Config ;
eslint-plugin-react ์ค์
import pluginReact from 'eslint-plugin-react' ;
import type { Linter } from 'eslint' ;
export default {
plugins : { '@react' : pluginReact } ,
rules : {
// boolean์ ๋ฐ๋์ isBoolean ํํ๋ก ํ๊ธฐ๋จ
'@react/boolean-prop-naming' : 'error' ,
// ๋ฒํผ์ ๋ฐ๋์ ๋ช
์์ ์ธ ํ์
์ ๊ฐ์ง๋๋ก ๊ฐ์
'@react/button-has-type' : 'error' ,
// ์ปดํฌ๋ํธ๋ ํญ์ DisplayName๋ฅผ ๊ฐ์ง
'@react/display-name' : 'error' ,
// ๊ธฐ๋ช
์ปดํฌ๋ํธ๋ ํจ์ํ์ผ๋ก, ์ต๋ช
์ปดํฌ๋ํธ๋ ์ ๋ก์ฐ ๋ฉ์๋๋ก ๊ฐ์
'@react/function-component-definition' : [
'error' ,
{
namedComponents : 'function-declaration' ,
unnamedComponents : 'arrow-function'
}
] ,
// useState์ get, set ๊ฐ์ฒด๋ช
์ ๋์นญ์ ์ผ๋ก ๊ตฌ์ฑ๋จ
'@react/hook-use-state' : 'error' ,
// boolean ํ๋กํผํฐ๋ ์์์ ํํ ๊ฐ์
'@react/jsx-boolean-value' : [
'error' ,
'never'
] ,
// JSX๋ ๋ฐ๋์ .jsx ํน์ .tsx ํ์ฅ์๋ฅผ ๊ฐ์ง
'@react/jsx-filename-extension' : [
'error' ,
{
extensions : [
'.jsx' ,
'.tsx'
]
}
] ,
// ํธ๋ค๋ฌ ๋ฉ์๋ ๋ฐ ํ๋กํผํฐ ๋ช
์นญ ๊ท์ฝ ๊ฐ์
'@react/jsx-handler-names' : 'error' ,
// JSX ๋ฐ๋ณต๋ฌธ ์, key ํ๋กํผํฐ๋ฅผ ๋ฐ๋์ ํฌํจํ๋๋ก ๊ฐ์
'@react/jsx-key' : 'error' ,
// ์ฃผ์์ด ํ
์คํธ ๋
ธ๋์์ ์ฌ์ฉ๋๋ ๊ฒ์ ๋ฐฉ์งํจ
'@react/jsx-no-comment-textnodes' : 'error' ,
// ๋ถํ์ํ ์ฌ๋ ๋๋ง์ ์ ๋ฐํ๋ ๊ฐ ํ ๋น ๋ฐฉ์ง
'@react/jsx-no-constructed-context-values' : 'error' ,
// ์ค๋ณต ํ๋กํผํฐ ๋ฐฉ์ง
'@react/jsx-no-duplicate-props' : 'error' ,
// aํ๊ทธ ์ทจ์ฝ์ ๋ฐฉ์ง
'@react/jsx-no-target-blank' : 'error' ,
// ์ ์๋์ง ์์ ์ปดํฌ๋ํธ ํธ์ถ ๋ฐฉ์ง
'@react/jsx-no-undef' : 'error' ,
// ๋ถํ์ํ ํ๋๊ทธ๋จผํธ ๋ฐฉ์ง
'@react/jsx-no-useless-fragment' : 'error' ,
// ์ค๋ณต ์คํ๋ ๋ ํ๋กํผํฐ ํ ๋น ๋ฐฉ์ง
'@react/jsx-props-no-spread-multi' : 'error' ,
// ๋ฏธ์ฌ์ฉ JSX ๋ฐฉ์ง
'@react/jsx-uses-vars' : 'error' ,
// ์ด์ ์ํ ๊ธฐ๋ฐ ๋ณ๊ฒฝ ์, ๋ฉ์๋์ ์ธ์๋ก ์ฐธ์กฐํ๋๋ก ๊ฐ์
'@react/no-access-state-in-setstate' : 'error' ,
// children์ ํ๋กํผํฐ๋ก ์ ๋ฌํ๋ ๊ฒ์ ๋ฐฉ์ง
'@react/no-children-prop' : 'error' ,
// dangerouslySetInnerHTML ํ๋กํผํฐ์ children ๋ณํ ๊ธ์ง
'@react/no-danger-with-children' : 'error' ,
// deprecated ๋ฌธ๋ฒ ์ฌ์ฉ ๋ฐฉ์ง
'@react/no-deprecated' : 'error' ,
// state ์ง์ ๋ณ๊ฒฝ ๋ฐฉ์ง
'@react/no-direct-mutation-state' : 'error' ,
// findDOMNode ๋ฉ์๋ ์ฌ์ฉ ๋ฐฉ์ง
'@react/no-find-dom-node' : 'error' ,
// ์ ํจํ์ง ์์ HTML ์์ฑ ์ฌ์ฉ ๋ฐฉ์ง
'@react/no-invalid-html-attribute' : 'error' ,
// isMount ๋ฉ์๋ ์ฌ์ฉ ๋ฐฉ์ง
'@react/no-is-mounted' : 'error' ,
// ์ปดํฌ๋ํธ์ ๋ฐํ๊ฐ์ ๋ณ์๋ก ์ฌ์ฉํ์ง ์๋๋ก ๋ฐฉ์ง
'@react/no-render-return-value' : 'error' ,
// ํจ์ํ ์ปดํฌ๋ํธ์์ this ํธ์ถ ๋ฐฉ์ง
'@react/no-this-in-sfc' : 'error' ,
// ์คํ ๋ฐฉ์ง
'@react/no-typos' : 'error' ,
// ๋ฌธ์์ด ์ด์ค์ผ์ดํ ๊ฐ์
'@react/no-unescaped-entities' : 'error' ,
// ์๋ ค์ง์ง ์์ ํ๋กํผํฐ ์ฌ์ฉ ๋ฐฉ์ง
'@react/no-unknown-property' : 'error' ,
// ๋ฏธ์ฌ์ฉ ํ๋กํผํฐ ์ ์ธ ๋ฐฉ์ง
'@react/no-unused-prop-types' : 'error' ,
// ๋ฏธ์ฌ์ฉ ์ํ ์ ์ธ ๋ฐฉ์ง
'@react/no-unused-state' : 'error' ,
// ํ๋กํผํฐ ์์ ๋ฐฉ์ง
'@react/prefer-read-only-props' : 'error' ,
// ํจ์ํ ์ปดํฌ๋ํธ ๊ฐ์
'@react/prefer-stateless-function' : 'error' ,
// ํ๋กํผํฐ ํ์
์ ์ธ ๊ฐ์
'@react/prop-types' : 'error' ,
// children์ ๊ฐ์ง ์ ์๋ DOM์ children ํ ๋น ๋ฐฉ์ง
'@react/void-dom-elements-no-children' : 'error'
}
} satisfies Linter . Config ;
eslint-plugin-react-hooks ์ค์
import pluginReactHooks from 'eslint-plugin-react-hooks' ;
import type { Linter } from 'eslint' ;
export default {
files : [
'**/*.jsx' ,
'**/*.tsx'
] ,
plugins : { '@react-hooks' : pluginReactHooks } ,
rules : {
// ์ฒ ์ ํ ๋ํ๋์ ๋ฐฐ์ด ๊ถ๊ณ
'@react-hooks/exhaustive-deps' : 'error' ,
// react hook ๊ท์น์ ์๋ฐฐ๋๋ ์ฝ๋ ๋ฐฉ์ง
'@react-hooks/rules-of-hooks' : 'error' ,
// ๋ถ์์ ํ ๋ํ๋์ ๋ฐฐ์ด ์ ์ธ ๋ฐฉ์ง
'@tanstack/query/no-unstable-deps' : 'warn' ,
// ์์ ์ ์ธ QueryClient ์ ์ธ ๊ฐ์
'@tanstack/query/stable-query-client' : 'error'
}
} satisfies Linter . Config ;
eslint-plugin-sort-keys-fix ์ค์
import pluginSortKeysFix from 'eslint-plugin-sort-keys-fix' ;
import type { Linter } from 'eslint' ;
export default {
plugins : { '@sort-keys-fix' : pluginSortKeysFix } ,
rules : { '@sort-keys-fix/sort-keys-fix' : 'error' }
} satisfies Linter . Config ;
@stylistic/eslint-plugin ์ค์
import stylistic from '@stylistic/eslint-plugin' ;
import type { Linter } from 'eslint' ;
export default {
plugins : { '@stylistic' : stylistic } ,
rules : {
// ๋ฐฐ์ด ์์ดํ
์ด 3๊ฐ ์ด์์ด๋ผ๋ฉด, ๋ธ๋ผ์ผ์ ์ค๋ฐ๊ฟ ์ถ๊ฐ
'@stylistic/array-bracket-newline' : [
'error' ,
{
minItems : 2 ,
multiline : false
}
] ,
// ๋ฐฐ์ด ๋ธ๋ผ์ผ์ ๊ณต๋ฐฑ ๊ฐ์
'@stylistic/array-bracket-spacing' : [
'error' ,
'always'
] ,
// ๋ฐฐ์ด ์์ดํ
์ด 3๊ฐ ์ด์์ด๋ผ๋ฉด, ๊ฐ ์์์ ์ค๋ฐ๊ฟ ์ถ๊ฐ
'@stylistic/array-element-newline' : [
'error' ,
{
minItems : 2 ,
multiline : false
}
] ,
// ์ ๋ก์ฐ ๋ฉ์๋์ ํ๋ผ๋ฏธํฐ๋ ์ด๋ ํ ๊ฒฝ์ฐ์๋ ์๊ดํธ๋ก ๊ฐ์
'@stylistic/arrow-parens' : [
'error' ,
'always'
] ,
// ์ ๋ก์ฐ ๋ฉ์๋์ ํ์ดํ ์ ์์ ๊ณต๋ฐฑ ๊ฐ์
'@stylistic/arrow-spacing' : 'error' ,
// { ์ธ๋ผ์ธ ๋ธ๋ก ๋ธ๋ผ์ผ }์ ๊ณต๋ฐฑ ๊ฐ์
'@stylistic/block-spacing' : 'error' ,
// allman ์คํ์ผ ๊ฐ์
'@stylistic/brace-style' : [
'error' ,
'allman'
] ,
// ๋ถํ์ํ ์ปด๋ง ๋๊ธ๋ง ๋ฐฉ์ง
'@stylistic/comma-dangle' : 'error' ,
// ์ปด๋ง๋ ๋ฐ๋์, ์ด๋ ๊ฒ
'@stylistic/comma-spacing' : 'error' ,
// ํ๋กํผํฐ ๋ธ๋ผ์ผ์ ์คํ์ด์ฑ ์ ๊ฑฐ
'@stylistic/computed-property-spacing' : 'error' ,
// ๋ธ๋ก ๋ธ๋ผ์ผ์ ํญ์ ์ค๋ฐ๊ฟ ๊ฐ์
'@stylistic/curly-newline' : [
'error' ,
'always'
] ,
// ์ฒด์ด๋ ์ .์ ํญ์ ํ๋กํผํฐ์ ์ถ๊ฐ๋จ
'@stylistic/dot-location' : [
'error' ,
'property'
] ,
// EOL ์ ๊ฑฐ
'@stylistic/eol-last' : [
'error' ,
'never'
] ,
// ๋์ฒด ๋๊ฐ ๋ฉ์๋๋ฅผ fn ()๋ก ํธ์ถํจ?
'@stylistic/function-call-spacing' : 'error' ,
// ํ๋ผ๋ฏธํฐ ํ ์ค ๊ฐ์
'@stylistic/function-paren-newline' : [
'error' ,
'never'
] ,
// *๋ฉ์๋ ๊ณต๋ฐฑ ์ ๊ฑฐ
'@stylistic/generator-star-spacing' : 'error' ,
// ์ ๋ก์ฐ ๋ฉ์๋์ ์ธ๋ผ์ธ ๋ฐํ๊ฐ ํ ์ค ๊ฐ์
'@stylistic/implicit-arrow-linebreak' : 'error' ,
// ์ธ๋ดํธ ํญ ๊ฐ์
'@stylistic/indent' : [
'error' ,
'tab'
] ,
// ๋ฐ์ด๋๋ฆฌ ์ฐ์ฐ์ ์ธ๋ดํธ ์ง์
'@stylistic/indent-binary-ops' : [
'error' ,
'tab'
] ,
// JSX ํด๋ก์ง ๋ธ๋ผ์ผ ์์น๊ฐ ํ๊ทธ ์์น์ ์์กดํ๋๋ก ๊ฐ์
'@stylistic/jsx-closing-bracket-location' : 'error' ,
// JSX ํด๋ก์ง ํ๊ทธ ์์น๊ฐ ํ๊ทธ ์์น์ ์์กดํ๋๋ก ๊ฐ์
'@stylistic/jsx-closing-tag-location' : 'error' ,
// JSX ํ ๋น ๊ท์น ๊ฐ์
'@stylistic/jsx-curly-brace-presence' : [
'error' ,
{
children : 'never' ,
props : 'never'
}
] ,
// JSX ํ
ํ๋ฆฟ ์ค๋ฐ๊ฟ ๊ท์น ๊ฐ์
'@stylistic/jsx-curly-newline' : [
'error' ,
{
multiline : 'consistent' ,
singleline : 'consistent'
}
] ,
// JSX ํ
ํ๋ฆฟ ๊ณต๋ฐฑ ํญ์ ์ ๊ฑฐ
'@stylistic/jsx-curly-spacing' : [
'error' ,
{
children : true ,
when : 'never'
}
] ,
// JSX ํ๋กํผํฐ ํ ๋น ๊ธฐํธ ๊ณต๋ฐฑ ์ ๊ฑฐ
'@stylistic/jsx-equals-spacing' : 'error' ,
// JSX ์ฒซ ํ๋กํผํฐ ์ค๋ฐ๊ฟ ๊ท์น ๊ฐ์
'@stylistic/jsx-first-prop-new-line' : 'error' ,
// JSX ๋ฉ์๋ ํธ์ถ ๊ท์น ๊ฐ์
'@stylistic/jsx-function-call-newline' : 'error' ,
// JSX ํ๋กํผํฐ ์ค๋ฐ๊ฟ ๊ท์น ๊ฐ์
'@stylistic/jsx-max-props-per-line' : [
'error' ,
{ when : 'multiline' }
] ,
// JSX ํ๋กํผํฐ ๋ค์ค ๊ณต๋ฐฑ ์ ๊ฑฐ
'@stylistic/jsx-props-no-multi-spaces' : 'error' ,
// JSX ํ๋กํผํฐ ๋ฐ์ดํ ๋๋ธ ๊ฐ์
'@stylistic/jsx-quotes' : 'error' ,
// JSX ์
ํ ํด๋ก์ง ๊ฐ์
'@stylistic/jsx-self-closing-comp' : [
'error' ,
{
component : true ,
html : true
}
] ,
// JSX ํ๋กํผํฐ ํค ์ ๋ ฌ ๊ฐ์
'@stylistic/jsx-sort-props' : [
'error' ,
{
callbacksLast : true ,
shorthandLast : true
}
] ,
// JSX ์
ํ ํด๋ก์ง ์ ํด๋ก์ง ํ๊ทธ ์ ์ ๊ณต๋ฐฑ ๊ฐ์
'@stylistic/jsx-tag-spacing' : [
'error' ,
{ beforeSelfClosing : 'always' }
] ,
// JSX ๋ํ ๊ท์น ๊ฐ์
'@stylistic/jsx-wrap-multilines' : [
'error' ,
{
arrow : 'parens-new-line' ,
assignment : 'parens-new-line' ,
condition : 'parens-new-line' ,
declaration : 'parens-new-line' ,
logical : 'parens-new-line' ,
prop : 'parens-new-line' ,
propertyValue : 'parens-new-line' ,
return : 'parens-new-line'
}
] ,
// ํค ์ฝ๋ก ๊ณต๋ฐฑ์ ํญ์ ํ์์๋ง ๋ถ๋๋ก ๊ฐ์
'@stylistic/key-spacing' : 'error' ,
// ํค์๋์ ๊ณต๋ฐฑ ๊ฐ์
'@stylistic/keyword-spacing' : 'error' ,
// ๋ฉค๋ฒ ๊ตฌ๋ถ์ ๊ฐ์
'@stylistic/member-delimiter-style' : 'error' ,
// ์ฃผ์ ๊ตฌ๋ถ ๋ผ์ธ ๊ธฐ์ค์ผ๋ก ๊ฐ์
'@stylistic/multiline-comment-style' : [
'error' ,
'separate-lines'
] ,
// new ํด๋์ค์ ๋ฐ๋์ ํ๋ผ๋ฏธํฐ ๊ดํธ ๋๋ฐ ๊ฐ์
'@stylistic/new-parens' : 'error' ,
// ๋๋ฒ์งธ ์ฒด์ด๋๋ถํฐ ์ค๋ก ๊ตฌ๋ถํ๋๋ก ๊ฐ์
'@stylistic/newline-per-chained-call' : [
'error' ,
{ ignoreChainWithDepth : 1 }
] ,
// ์ ๋ก์ฐ ๋ฉ์๋ ๋ฐํ๊ฐ ํผ๋ ๋ฐฉ์ง
'@stylistic/no-confusing-arrow' : 'error' ,
// ๋ถํ์ํ ์ธ๋ฏธ์ฝ๋ก ๋ฐฉ์ง
'@stylistic/no-extra-semi' : 'error' ,
// ํ๋กํ
์ซ์ ๋ฐฉ์ง
'@stylistic/no-floating-decimal' : 'error' ,
// ํญ๊ณผ ๊ณต๋ฐฑ ํผ์ฉ ๋ฐฉ์ง
'@stylistic/no-mixed-spaces-and-tabs' : 'error' ,
// ๋ค์ค ๊ณต๋ฐฑ ๋ฐฉ์ง
'@stylistic/no-multi-spaces' : 'error' ,
// ๋ค์ค ์ค๋ฐ๊ฟ ๋ฐฉ์ง
'@stylistic/no-multiple-empty-lines' : 'error' ,
// ํธ๋ฆด๋ง ๊ณต๋ฐฑ ๋ฐฉ์ง
'@stylistic/no-trailing-spaces' : 'error' ,
// ํ๋กํผํฐ ์ฝค๋ง์ ์ ์ ๊ณต๋ฐฑ ๋ฐฉ์ง
'@stylistic/no-whitespace-before-property' : 'error' ,
// ์ค๋ธ์ ํธ ๋ธ๋ผ์ผ ์ค๋ฐ๊ฟ ๊ท์น ๊ฐ์
'@stylistic/object-curly-newline' : [
'error' ,
{
minProperties : 2 ,
multiline : true
}
] ,
// ์ค๋ธ์ ํธ ๋ธ๋ผ์ผ ๊ณต๋ฐฑ ๊ฐ์
'@stylistic/object-curly-spacing' : [
'error' ,
'always'
] ,
// ์ค๋ธ์ ํธ ์์ ์ค๋ฐ๊ฟ ๊ท์น ๊ฐ์
'@stylistic/object-property-newline' : [
'error' ,
{ allowAllPropertiesOnSameLine : false }
] ,
// ๋ถํ์ํ ๋ธ๋ญ ํจ๋ฉ ๋ฐฉ์ง
'@stylistic/padded-blocks' : [
'error' ,
'never'
] ,
// ํค์๋๋ณ ํจ๋ฉ ๊ท์น ์ง์
'@stylistic/padding-line-between-statements' : [
'error' ,
{
blankLine : 'always' ,
next : 'return' ,
prev : '*'
} ,
{
blankLine : 'always' ,
next : '*' ,
prev : [
'const' ,
'let' ,
'var'
]
} ,
{
blankLine : 'any' ,
next : [
'const' ,
'let' ,
'var'
] ,
prev : [
'const' ,
'let' ,
'var'
]
} ,
{
blankLine : 'always' ,
next : '*' ,
prev : 'directive'
} ,
{
blankLine : 'any' ,
next : 'directive' ,
prev : 'directive'
} ,
{
blankLine : 'always' ,
next : '*' ,
prev : [
'case' ,
'default'
]
} ,
{
blankLine : 'always' ,
next : [
'enum' ,
'interface' ,
'type'
] ,
prev : '*'
}
] ,
// ํ๋กํผํฐ ๋ฐ์ดํ๋ ํ์ํ ๊ฒฝ์ฐ์๋ง ์ง์
'@stylistic/quote-props' : [
'error' ,
'as-needed'
] ,
// ๋ฌธ์์ด์ ์ฑ๊ธ ๋ฐ์ดํ ๊ฐ์
'@stylistic/quotes' : [
'error' ,
'single'
] ,
// ๊ฐ๋ณ ์คํ๋ ๋์ ๊ณต๋ฐฑ ์ ๊ฑฐ
'@stylistic/rest-spread-spacing' : 'error' ,
// ์ธ๋ฏธ์ฝ๋ก ๊ฐ์
'@stylistic/semi' : 'error' ,
// ์ธ๋ฏธ์ฝ๋ก ์ ์ ๊ณต๋ฐฑ ๋ฐฉ์ง
'@stylistic/semi-spacing' : 'error' ,
// ์ธ๋ฏธ์ฝ๋ก ์ ๋ฐ๋์ ๊ตฌ๋ฌธ ๋์ ์์น
'@stylistic/semi-style' : 'error' ,
// ๋ธ๋ก ์ ์ ๊ณต๋ฐฑ ๊ฐ์
'@stylistic/space-before-blocks' : 'error' ,
// ๋ฉ์๋ ํ๋ผ๋ฏธํฐ ๊ดํธ ๊ณต๋ฐฑ ๋ฐฉ์ง
'@stylistic/space-before-function-paren' : [
'error' ,
'never'
] ,
// ์ฐ์ฐ์ ๊ณต๋ฐฑ ๊ฐ์
'@stylistic/space-infix-ops' : 'error' ,
// ๋จํญ์ฐ์ฐ์ ๊ณต๋ฐฑ ์ ๊ฑฐ
'@stylistic/space-unary-ops' : 'error' ,
// ์ฃผ์ ๊ณต๋ฐฑ ์ฒ๋ฆฌ
'@stylistic/spaced-comment' : 'error' ,
// case ์ฝ๋ก ๊ณต๋ฐฑ ์ฒ๋ฆฌ
'@stylistic/switch-colon-spacing' : 'error' ,
// ํ
ํ๋ฆฟ ๋ฌธ๋ฒ ๋ด๋ถ ๊ณต๋ฐฑ ๋ฐฉ์ง
'@stylistic/template-curly-spacing' : 'error' ,
// ํ
ํ๋ฆฟ ํ๊ทธ ๊ณต๋ฐฑ ์ถ๊ฐ
'@stylistic/template-tag-spacing' : [
'error' ,
'never'
] ,
// ํ์
์ด๋
ธํ
์ด์
ํํ ๊ณต๋ฐฑ๋ง ํ์ฉ
'@stylistic/type-annotation-spacing' : 'error' ,
// <์ ๋ค๋ฆญ, ํ์
> ๊ณต๋ฐฑ ์ฒ๋ฆฌ
'@stylistic/type-generic-spacing' : 'error' ,
// ํํ ํ์
๊ณต๋ฐฑ ์ฒ๋ฆฌ
'@stylistic/type-named-tuple-spacing' : 'error' ,
// (IIFE ํธ์ถ ๋ฐฉ์)() ๊ฐ์
'@stylistic/wrap-iife' : [
'error' ,
'inside'
]
}
} satisfies Linter . Config ;
@tanstack/eslint-plugin-query ์ค์
import pluginQuery from '@tanstack/eslint-plugin-query' ;
import type { Linter } from 'eslint' ;
export default {
plugins : { '@tanstack/query' : pluginQuery } ,
rules : {
// ์ฒ ์ ํ ๋ํ๋์ ๊ฐ์
'@tanstack/query/exhaustive-deps' : 'error' ,
// ๋ถํ์ํ ๊ตฌ์กฐ ํ๊ดด ๊ฐ์ฒด ์ ์ธ ๋ฐฉ์ง
'@tanstack/query/no-rest-destructuring' : 'error' ,
// ๋ถ์์ ํ ๋ํ๋์ ์ ์ธ ๋ฐฉ์ง
'@tanstack/query/no-unstable-deps' : 'warn' ,
// ์์ ์ ์ธ QueryClient ์ ์ธ ๊ฐ์
'@tanstack/query/stable-query-client' : 'error'
}
} satisfies Linter . Config ;
import tseslint from 'typescript-eslint' ;
import type { ConfigArray } from 'typescript-eslint' ;
const config : ConfigArray [ number ] = {
files : [
'**/*.ts' ,
'**/*.tsx' ,
'**/*.cts' ,
'**/*.mts'
] ,
plugins : { '@typescript-eslint' : tseslint . plugin } ,
rules : {
// ์ค๋ฒ๋ก๋ฉ๋ ๋ฉ์๋๋ ๋๋ํ ๋ฐฐ์นํ๋๋ก ๊ฐ์
'@typescript-eslint/adjacent-overload-signatures' : 'error' ,
// ์ ๋ค๋ฆญ ํ์
์ ๊ตฌ์ฑํ ๋ ์ ์ธํ ๋น๋ถ์ ๋ช
์ํ๋๋ก ๊ฐ์
'@typescript-eslint/consistent-generic-constructors' : 'error' ,
// ํ์
์ ์ธ ์ ๊ฐ๋ฅํ ๊ฒฝ์ฐ, interface๋ฅผ ํ์ฉํ๋๋ก ๊ฐ์
'@typescript-eslint/consistent-type-definitions' : 'error' ,
// type export ๋ช
์ ๊ฐ์
'@typescript-eslint/consistent-type-exports' : 'error' ,
// export ํค์๋ ๋ค์ type ๋ช
์ ๊ฐ์
'@typescript-eslint/consistent-type-imports' : 'error' ,
// return ํ์
๋ช
์ ๊ฐ์
'@typescript-eslint/explicit-function-return-type' : 'error' ,
// ์ ๊ทผ์ ๋ช
์ ๊ฐ์
'@typescript-eslint/explicit-member-accessibility' : 'error' ,
// ๋ฉ์๋์ ํ๋ผ๋ฏธํฐ ๋ฐ return ํ์
๋ช
์ ๊ฐ์
'@typescript-eslint/explicit-module-boundary-types' : 'error' ,
// ๋ฉค๋ฒ ์ ๋ ฌ ๊ฐ์
'@typescript-eslint/member-ordering' : 'error' ,
// ํ์
์ ๋ฉ์๋๋ ํ๋กํผํฐ ํํ๋ก ํ๊ธฐ
'@typescript-eslint/method-signature-style' : 'error' ,
// ๋ฐฐ์ด์ delete ๋ช
๋ น์ด ๊ธ์ง
'@typescript-eslint/no-array-delete' : 'error' ,
// toString์ ํ์ฉํ ๋ฌธ์์ด ๋ณํ ๋ฐฉ์ง
'@typescript-eslint/no-base-to-string' : 'error' ,
// null ๋ณํฉ ์ฐ์ฐ์ ์ฌ์ฉ ๋ฐฉ์ง
'@typescript-eslint/no-confusing-non-null-assertion' : 'error' ,
// ํผ๋๋๋ void ํํ ๋ฐฉ์ง
'@typescript-eslint/no-confusing-void-expression' : 'error' ,
// @deprecated ๋ฉ์๋ ์ฌ์ฉ ๊ธ์ง
'@typescript-eslint/no-deprecated' : 'error' ,
// ์ค๋ณต๋ enum ๊ฐ ๋ฐฉ์ง
'@typescript-eslint/no-duplicate-enum-values' : 'error' ,
// ์ค๋ณต๋ ํ์
ํ ๋น ๋ฐฉ์ง
'@typescript-eslint/no-duplicate-type-constituents' : 'error' ,
// any ํ์
์ฌ์ฉ ๋ฐฉ์ง
'@typescript-eslint/no-explicit-any' : 'error' ,
// non null ์ฐ์ฐ์ ์ฌ์ฉ ๋ฐฉ์ง
'@typescript-eslint/no-extra-non-null-assertion' : 'error' ,
// Promise ๊ฐ์ฒด์ ๊ฒฐ๊ณผ๋ฅผ ๋ช
์์ ์ผ๋ก ๋ค๋ฃจ๋๋ก ๊ตฌ์ฑ
'@typescript-eslint/no-floating-promises' : 'error' ,
// for in ๋ฌธ๋ฒ ๋ฐฉ์ง
'@typescript-eslint/no-for-in-array' : 'error' ,
// ์ฌ์ด๋ ์ดํํธ๋ฅผ ์ ๋ฐํ๋ import ๋ฐฉ์ง
'@typescript-eslint/no-import-type-side-effects' : 'error' ,
// ์ ํจํ์ง ์์ void ํ์
์ฌ์ฉ ๋ฐฉ์ง
'@typescript-eslint/no-invalid-void-type' : 'error' ,
// ์๋ฏธ์๋ void ์ฐ์ฐ์ ์ฌ์ฉ ๋ฐฉ์ง
'@typescript-eslint/no-meaningless-void-operator' : 'error' ,
// ์ค์ฉ๋ new ๋ฉ์๋ ์ฌ์ฉ ๋ฐฉ์ง
'@typescript-eslint/no-misused-new' : 'error' ,
// ์ค์ฉ๋ promise ์ฌ์ฉ ๋ฐฉ์ง
'@typescript-eslint/no-misused-promises' : [
'error' ,
{ checksVoidReturn : false }
] ,
// ์ค์ฉ๋ ์คํ๋ ๋ ์ฌ์ฉ ๋ฐฉ์ง
'@typescript-eslint/no-misused-spread' : 'error' ,
// !์ ?? ์ฐ์ฐ์ ๋์ ์ฌ์ฉ ๋ฐฉ์ง
'@typescript-eslint/no-non-null-asserted-nullish-coalescing' : 'error' ,
// ๋ถํ์ํ ํ์
์ค๋ณต ์ ์ธ ๋ฐฉ์ง
'@typescript-eslint/no-redundant-type-constituents' : 'error' ,
// ๋ถํ์ํ boolean ๋น๊ต ๋ฐฉ์ง
'@typescript-eslint/no-unnecessary-boolean-literal-compare' : 'error' ,
// ๋ถํ์ํ ์กฐ๊ฑด ๋ฐฉ์ง
'@typescript-eslint/no-unnecessary-condition' : 'error' ,
// ํด๋์ค ์์ฑ์์์์ ๋ถํ์ํ ํ๋ผ๋ฏธํฐ ์ ์ธ ๋ฐฉ์ง
'@typescript-eslint/no-unnecessary-parameter-property-assignment' : 'error' ,
// ๋ถํ์ํ ์ ๋ค๋ฆญ ํ์
์๋ต
'@typescript-eslint/no-unnecessary-type-arguments' : 'error' ,
// ์ ๋ค๋ฆญ ํ์
๋งค๊ฐ๋ณ์์ ๋ถํ์ํ extends ๋ฐฉ์ง
'@typescript-eslint/no-unnecessary-type-constraint' : 'error' ,
// ๋ถ์์ ํ ์ ์ธ ๋ณํฉ ๋ฐฉ์ง
'@typescript-eslint/no-unsafe-declaration-merging' : 'error' ,
// ๋ถ์์ ํ enum ๋น๊ต ๋ฐฉ์ง
'@typescript-eslint/no-unsafe-enum-comparison' : 'error' ,
// ๋ถ์์ ํ ํจ์ ํ์
๋ฐฉ์ง
'@typescript-eslint/no-unsafe-function-type' : 'error' ,
// ๋ถ์์ ํ ๋ฐํ ๋ฐฉ์ง
'@typescript-eslint/no-unsafe-return' : 'error' ,
// ๋ถ์์ ํ ํ์
ํ์ธ ๋ฐฉ์ง
'@typescript-eslint/no-unsafe-type-assertion' : 'error' ,
// ๋ถํ์ํ - ์ฐ์ฐ์ ๋ฐฉ์ง
'@typescript-eslint/no-unsafe-unary-minus' : 'error' ,
// ๋ฏธ์ฌ์ฉ ๋ณ์ ๋ฐฉ์ง
'@typescript-eslint/no-unused-vars' : 'error' ,
// ๋ฌด์๋ฏธํ ๋น export ๋ฐฉ์ง
'@typescript-eslint/no-useless-empty-export' : 'error' ,
// ๋ํผ ๊ฐ์ฒด ํ์
์ฌ์ฉ ๋ฐฉ์ง
'@typescript-eslint/no-wrapper-object-types' : 'error' ,
// filter์์ ํ๋์ ๊ฐ๋ง ์ ๊ทผํ ๊ฒฝ์ฐ, find๋ฅผ ํ์ฉํ๋๋ก ๊ฐ์
'@typescript-eslint/prefer-find' : 'error' ,
// ์์์ ํฌํจ ์ฌ๋ถ๋ includes๋ฅผ ํ์ฉํ๋๋ก ๊ฐ์
'@typescript-eslint/prefer-includes' : 'error' ,
// enum ๊ฐ์ ๋ช
์์ ์ผ๋ก ์ง์ ํ๋๋ก ๊ฐ์
'@typescript-eslint/prefer-literal-enum-member' : 'error' ,
// module ์ ์ธ ๋์ namespace ํค์๋๋ฅผ ํ์ฉํ๋๋ก ๊ฐ์
'@typescript-eslint/prefer-namespace-keyword' : 'error' ,
// || ๋์ ?? ์ฐ์ฐ์ ์ฌ์ฉ ๊ฐ์
'@typescript-eslint/prefer-nullish-coalescing' : 'error' ,
// && ๋์ ?. ๋ฐฉ์์ผ๋ก ๊ฐ์ ์ ๊ทผํ๋๋ก ๊ฐ์
'@typescript-eslint/prefer-optional-chain' : 'error' ,
// reduce ๋ฉ์๋๊ฐ ๊ตฌ์ฒด์ ์ธ ํ์
์ ๊ฐ์ง๋๋ก ๊ฐ์
'@typescript-eslint/prefer-reduce-type-parameter' : 'error' ,
// ๊ฐ๋ฅํ ๊ฒฝ์ฐ, startsWith, endsWith๋ฅผ ํ์ฉํ๋๋ก ๊ฐ์
'@typescript-eslint/prefer-string-starts-ends-with' : 'error' ,
// Promise๋ฅผ ๋ฐํํ๋ ๋ฉ์๋๋ ๋ฐ๋์ async ํค์๋ ๊ฐ์
'@typescript-eslint/promise-function-async' : 'error' ,
// ์ซ์ ๋ฐฐ์ด์์ ์ ๋ ฌ ์, ๋น๊ต ๋ฉ์๋๋ฅผ ๋ฃ๋๋ก ๊ฐ์
'@typescript-eslint/require-array-sort-compare' : 'error' ,
// ์ดํ์ ํ์
์ + ์ฐ์ฐ ๋ฐฉ์ง
'@typescript-eslint/restrict-plus-operands' : 'error' ,
// ํ
ํ๋ฆฟ ๋ฌธ์์ด์์ ์์ ํ ํ์
๋ง ํ์ฉ๋๋๋ก ๊ฐ์
'@typescript-eslint/restrict-template-expressions' : 'error' ,
// boolean ๋น๊ต ์, ๋ช
์์ ๋น๊ต๋ง์ ํ์ฉํจ
'@typescript-eslint/strict-boolean-expressions' : 'error' ,
// ๋ฉ์๋๋ฅผ ๋ณ์์ ํ ๋นํ ๋, this๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ๋ฐ์ธ๋ฉ๋๋๋ก ๊ฐ์
'@typescript-eslint/unbound-method' : 'error' ,
// catch์์ ์๋ฌ๋ unknown ํ์
์ ํ์ฉํ๋๋ก ๊ฐ์
'@typescript-eslint/use-unknown-in-catch-callback-variable' : 'error' ,
// TS๋ @typescript-eslint/no-unused-vars ๊ท์น์ผ๋ก ์ฒ๋ฆฌ
'no-unused-vars' : 'off'
}
} ;
export default config ;
eslint-plugin-unused-imports ์ค์
import pluginUnusedImports from 'eslint-plugin-unused-imports' ;
import type { Linter } from 'eslint' ;
export default {
plugins : { '@unused-imports' : pluginUnusedImports } ,
rules : { '@unused-imports/no-unused-imports' : 'error' }
} satisfies Linter . Config ;