Open6

TypeScriptプロジェクトの最強初期設定

todeskingtodesking

毎回最新最強構成を調べるの飽きた!!!!!
プリセット使うにしても結局中身が気になる!!!!!!!

todeskingtodesking

TypeScript

npm install -D typescript better-typescript-lib

早くTypeScriptデフォルトの型定義が正気になってbetter-typescript-libが不要になる時代が来てほしい。

Pretter + ESLint

# 基本
npm install -D prettier eslint eslint-config-prettier @typescript-eslint/eslint-plugin @typescript-eslint/parser
npm install -D eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-n eslint-plugin-promise eslint-plugin-unicorn eslint-plugin-unused-imports

# CSS
npm install -D stylelint stylelint-prettier

# React
npm install -D eslint-plugin-react eslint-plugin-react-hooks
todeskingtodesking

eslint.config.mjs

マジでこれ用意するわけ??? プロジェクト作るごとに???????

eslint実行時は ESLINT_USE_FLAT_CONFIG=true eslint -c eslint.config.mjs {args} する

eslint.config.mjs
import {FlatCompat} from '@eslint/eslintrc'
import js from '@eslint/js'
import reactPlugin from 'eslint-plugin-import'
import importPlugin from 'eslint-plugin-import'
import nPlugin from 'eslint-plugin-n'
import unusedImportsPlugin from 'eslint-plugin-unused-imports'
import unicornPlugin from 'eslint-plugin-unicorn'
import parser from '@typescript-eslint/parser'
import path from 'node:path'
import {fileURLToPath} from 'node:url'

const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)

const compat = new FlatCompat({
  baseDirectory: __dirname,
  recommendedConfig: js.configs.recommended,
});

export default [
  ...compat.extends(
    "eslint:recommended",
    "plugin:n/recommended",
    "plugin:import/recommended",
    "plugin:import/typescript",
    "plugin:@typescript-eslint/recommended-type-checked",
    "plugin:@typescript-eslint/stylistic-type-checked",
    "plugin:react/recommended",
    "plugin:react-hooks/recommended",
      "plugin:storybook/recommended",
    "prettier",
  ),
  {
    files: ["src/**/*.{ts,tsx}"],
    languageOptions: {
      ecmaVersion: "latest",
      sourceType: "module",
      parser,
      parserOptions: {
        project: [
          "tsconfig.json"
        ],
      },
    },
    linterOptions: {
      reportUnusedDisableDirectives: true,
    },
    plugins: {
      "unused-imports": unusedImportsPlugin,
      unicorn: unicornPlugin,
    },
    rules: {
      "no-extra-semi": "off",
      "@typescript-eslint/no-extra-semi": "error",
      "@typescript-eslint/no-non-null-assertion": "warn",
      "no-unused-vars": "off",
      "@typescript-eslint/no-unused-vars": "off",
      "unused-imports/no-unused-imports": "warn",
      "unused-imports/no-unused-vars": [
        "warn",
        {
          vars: "all",
          varsIgnorePattern: "^_",
          args: "after-used",
          argsIgnorePattern: "^_",
        },
      ],
      "react-hooks/exhaustive-deps": [
        "warn",
        {
          additionalHooks: "(useRecoilCallback|useRecoilTransaction_UNSTABLE)",
        },
      ],
      "@typescript-eslint/explicit-function-return-type": "off",
      "@typescript-eslint/explicit-module-boundary-types": "error",
      "@typescript-eslint/no-explicit-any": "off",
      "@typescript-eslint/consistent-type-definitions": ["warn", "type"],
      "import/order": ["error"],
      "import/namespace": "off", // Not works with flat config for some reason
      "unicorn/better-regex": ["error"],
      "unicorn/escape-case": ["error"],
      "unicorn/new-for-builtins": ["error"],
      "unicorn/no-array-callback-reference": ["error"],
      "unicorn/no-array-for-each": ["error"],
      "unicorn/no-array-method-this-argument": ["error"],
      "unicorn/no-for-loop": ["error"],
      "unicorn/no-instanceof-array": ["error"],
      "unicorn/no-invalid-remove-event-listener": ["error"],
      "unicorn/no-unnecessary-await": ["error"],
      "unicorn/no-unsafe-regex": ["error"],
      "unicorn/numeric-separators-style": ["error"],
      "unicorn/prefer-date-now": ["error"],
      "unicorn/prefer-modern-dom-apis": ["error"],
      "unicorn/prefer-modern-math-apis": ["error"],
      "unicorn/prefer-node-protocol": ["error"],
      "unicorn/throw-new-error": ["error"],
      "unicorn/switch-case-braces": ["error"],
      // Can't handle tsconfig by default
      "n/no-missing-import": "off",
    },
    settings: {
      react: {
        version: "detect",
      },
      "import/resolver": {
        typescript: {
          alwaysTryTypes: true,
          project: ["tsconfig.json"],
        },
      },
    },
  },
];
todeskingtodesking

stylelintrc.yml

plugins:
  - stylelint-prettier
rules:
  "prettier/prettier": true
todeskingtodesking

npm i @todesking/typescript-project-preset で全て終わらせる仕組みを作るとよさそう