React.FCとReact.FunctionComponentはESLintで禁止するべき

React.FCとは

React.FC (React.FunctionComponent)とは関数コンポーネント用の型エイリアスです。TypeScriptでReactを書き始めた頃によく使われていました。

FCはFunction Componentの略で、React.FCとReact.FunctionComponentは同じ意味です。

App.tsx
// React.FCとReact.FunctionComponentは同じ
const Message1: React.FC<{ message: string }> = ({ message }) => {
  return <div>{message}</div>
}

const Message2: React.FunctionComponent<{ message: string }> = ({ message }) => (
	<div>{message}</div>
)

React.FCの3つの問題点

React.FCは昔はよく使われましたが、現在は以下の3つの問題があるため使われることは少なくなりました。

問題1 childrenが暗黙に許可される

以下のように設計上いらないchildrenまで許可されてしまいます。

App.tsx
const Button: React.FC<{ label: string }> = ({ label }) => {
  return <button>{label}</button>
}

<Button label="送信">余計なchildren</Button>

問題2 ジェネリクスと相性が悪い

以下のように書くことができないので、ジェネリクスと相性が悪いです。

App.tsx
const List: React.FC<{ items: T[] }> = {}

問題3 冗長でメリットがない

React.FCを使うメリットがないので、現在は以下の書き方が推奨されています。

App.tsx
const Foo = (props: Props) => {}

以上の3つの問題があるため、現在ではReact.FCを使用しない書き方をしたほうが良いです。

App.tsx
type MessageProps = { message: string }

function Message({ message }: MessageProps) {
  return <div>{message}</div>
}

function App() {
  return (
    <>
      <Message message="Hello" />
      <Message message="World!" />
    </>
  )
}

export default App

React.FCをESLintで検出する方法

React.FC (React.FunctionComponent)をESLintで検出するには以下のルールを追加します。

いまだにReact.FCの古い書き方をする人をたまに見かけるので、ESLintでルール化しておくと良いでしょう。

eslint.config.js
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'
import { defineConfig, globalIgnores } from 'eslint/config'

export default defineConfig([
  globalIgnores(['dist']),
  {
    files: ['**/*.{ts,tsx}'],
    extends: [
      js.configs.recommended,
      tseslint.configs.recommended,
      reactHooks.configs.flat.recommended,
      reactRefresh.configs.vite,
    ],
    languageOptions: {
      ecmaVersion: 2020,
      globals: globals.browser,
    },
    rules: {
      '@typescript-eslint/no-restricted-types': [
        'error',
        {
          types: {
            'React.FC': {
              message:
                'React.FCは使用しないでください。通常の関数 + Props型を使用してください。',
            },
            'React.FunctionComponent': {
              message: 'React.FunctionComponentは使用しないでください。',
            },
          },
        },
      ],
    },
  },
])
React.FCを使用したサンプル(npm run lintでエラーになる)❌️

React.FCを使用したサンプル(npm run lintでエラーになる)❌️

React.FCを使用しないサンプル(npm run lintでエラーにならない)✅️