Specify PascalCase Naming Convetion for Variables of JSX.Element Type in eslint Rules

Issue

I’d like to enforce PascalCase for variables of type JSX.Element in my React+Typescript project. I frequently use the following pattern to create functional components, and I like to distinguish my eponymous export by giving it a PascalCase name:

//MyComponent.tsx
//PascalCase for MyComponent 
export const MyComponent= (): JSX.Element =>{  
  return (
    <div>
      My Component
    </div>
  )
}
export default MyComponent

With my current linter settings, I get a warning that Variable name `MyComponent` must match one of the following formats: camelCase, UPPER_CASE. How can I add a rule to my linter settings that will enforce PascalCase for variables of type JSX.Element?

Here’s my current .eslintrc.json:

{
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaVersion": 2018,
    "sourceType": "module"
  },
  "plugins": ["@typescript-eslint", "react-hooks"],
  "extends": [
    "plugin:react/recommended",
    "plugin:@typescript-eslint/recommended"
  ],
  "rules": {
    "react-hooks/rules-of-hooks": "error",
    "react-hooks/exhaustive-deps": "warn",
    "react/prop-types": "off",
    "@typescript-eslint/naming-convention": "warn",
    "@typescript-eslint/explicit-function-return-type": [
      "warn",
      {
        "allowExpressions": true
      }
    ]
  },
  "settings": {
    "react": {
      "pragma": "React",
      "version": "detect"
    }
  }
}

Solution

Looks like it is not currently possible at the point of declaration (see link below). However, the incorrect casing can’t proliferate beyond the file in which it is declared, as lowercase names are reserved for intrinsic types like div, span, etc.

// my-component.tsx
export const myComponent: FC<{}> = () => (
  <div>My Component</div>
);

export default myComponent;
// app.tsx
import { myComponent } from './my-component';

// Fails to compile with: Property 'myComponent' does not
// exist on type 'JSX.IntrinsicElements'.  TS2339
const App = (): JSX.Element => <myComponent />;

In the case of a default export, the name used in the declaring file is effectively erased, as it’s simply assigned to whatever name is chosen in the importing file:

// app.tsx
import SomeOtherName from './my-component';

const App = (): JSX.Element => <SomeOtherName />;

Discussion about not having a rule specific to React components here: typescript-eslint/issues/2607

Additionally – there’s no guarantee that a function that returns a
JSX.Element is in fact a react component. Utility functions that
return JSX.Element, but aren’t react components are a relatively
common practice, which would cause false-positives.

Answered By – Eric Haynes

Answer Checked By – Terry (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.