Auto format Tsx files in VSCode

Assuming you’ve got eslint extension installed on Visual Studio Code, you should add the following to your settings.

Install dependencies

using specific stable versions:

npm install --save-dev @types/react@16.9.34 @types/react-dom@16.9.6 @typescript-eslint/eslint-plugin@^5.20.0 @typescript-eslint/parser@^5.20.0 eslint@^8.13.0 eslint-config-prettier@^8.5.0 eslint-plugin-prettier@^4.0.0 eslint-plugin-react@^7.29.4 prettier@2.6.2 react-scripts@3.4.1

using latest stable versions:

npm install --save-dev @types/react @types/react-dom @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint eslint-config-prettier eslint-plugin-prettier eslint-plugin-react prettier react-scripts

using airbnb latest stable versions:

npm i -D prettier eslint eslint-config-airbnb-typescript eslint-config-prettier eslint-plugin-import eslint-plugin-jsx-a11y@^6.2.3 eslint-plugin-prettier eslint-plugin-react eslint-plugin-react-hooks

.eslintrc.js

// https://www.google.com/search?channel=fs&client=ubuntu&q=%40typescript-eslint%2Feslint-plugin%2Fdist%2Fconfigs%2Fbase.json
// https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/configs/base.ts
// fix base.json
const { join } = require('upath');
const { writeFileSync, existsSync } = require('fs');
const dest = 'node_modules/@typescript-eslint/eslint-plugin/dist';
const filebase = join(__dirname, dest, 'configs/base.json');
if (!existsSync(filebase)) {
  const base = {
    parser: '@typescript-eslint/parser',
    parserOptions: { sourceType: 'module' },
    plugins: ['@typescript-eslint']
  };
  writeFileSync(filebase, JSON.stringify(base));
}

exports = {
  root: true,
  env: {
    browser: true,
    commonjs: true,
    es6: true,
    node: true
  },
  globals: {
    Atomics: 'readonly',
    SharedArrayBuffer: 'readonly'
  },
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaFeatures: {
      jsx: true
    },
    ecmaVersion: 2018,
    sourceType: 'module'
  },
  extends: [
    'plugin:react/recommended',
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:prettier/recommended'
  ],
  plugins: ['react', '@typescript-eslint'],
  rules: {
    'arrow-body-style': 'off',
    'prefer-arrow-callback': 'off'
  }
};

.eslintrc.js with airbnb

// https://www.google.com/search?channel=fs&client=ubuntu&q=%40typescript-eslint%2Feslint-plugin%2Fdist%2Fconfigs%2Fbase.json
// https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/configs/base.ts

const { join } = require('upath');
const { writeFileSync, existsSync } = require('fs');
const dest = 'node_modules/@typescript-eslint/eslint-plugin/dist';
const filebase = join(__dirname, dest, 'configs/base.json');
if (!existsSync(filebase)) {
  const base = {
    parser: '@typescript-eslint/parser',
    parserOptions: { sourceType: 'module' },
    plugins: ['@typescript-eslint']
  };
  writeFileSync(filebase, JSON.stringify(base));
}

exports = {
  root: true,
  parser: '@typescript-eslint/parser',
  parserOptions: {
    project: './tsconfig.json',
    tsconfigRootDir: '.'
  },
  plugins: ['@typescript-eslint'],
  extends: [
    'plugin:prettier/recommended',
    'airbnb-typescript',
    'prettier',
    'prettier/@typescript-eslint',
    'prettier/react'
  ],
  rules: {
    // Make prettier code formatting suggestions more verbose.
    'prettier/prettier': ['warn'],
    // Disable <Fragment> => <> replacement. Feel free to change
    'react/jsx-fragments': 'off',
    // Disable prefer default export
    'import/prefer-default-export': 'off'
  },
  overrides: [
    {
      files: ['**/*.tsx'],
      rules: {
        'react/prop-types': 'off',
        'react/jsx-props-no-spreading': 'off'
      }
    }
  ]
};

.prettierrc

{
  "$schema": "https://json.schemastore.org/prettierrc",
  "semi": true,
  "printWidth": 120,
  "singleQuote": true,
  "trailingComma": "none",
  "tabWidth": 2
}

.vscode/settings.json

{
  "eslint.format.enable": true,
  "editor.formatOnSave": false,
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact",
  ],
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true,
    "source.fixAll.stylelint": true
  }
}

tsconfig.json

{
  "include": [
    "./src/*"
  ],
  "compilerOptions": {
    "lib": [
      "dom",
      "es2015"
    ],
    "jsx": "react",
    "esModuleInterop": true,
    "target": "es5",
    "allowJs": true,
    "noImplicitAny": false,
    "skipLibCheck": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true
  }
}

example package.json devDependencies

{
  "devDependencies": {
    "@types/react": "16.9.34",
    "@types/react-dom": "16.9.6",
    "@typescript-eslint/eslint-plugin": "^5.20.0",
    "@typescript-eslint/parser": "^5.20.0",
    "eslint": "^8.13.0",
    "eslint-config-prettier": "^8.5.0",
    "eslint-plugin-prettier": "^4.0.0",
    "eslint-plugin-react": "^7.29.4",
    "prettier": "2.6.2",
    "react-scripts": "3.4.1"
  }
}

manual run with scripts package.json

{
  "scripts": {
    "lint": "eslint --ext .js,.jsx,.ts,.tsx src --color",
    "format": "prettier --write src/**/*.{ts,tsx,scss,css,json}"
  }
}