mirror of
https://github.com/apache/airflow.git
synced 2026-11-06 13:38:01 +00:00
React.FC adds nothing over annotating the props parameter directly, and the UI packages were split between the two styles. All of them compile with the automatic JSX runtime, so no file needs a React import at all -- the namespace survived only as habit. ESLint now rejects both patterns so they cannot creep back in. Two rules are needed rather than one: @types/react declares `export as namespace React`, so `React.FC` type-checks in files that never import React, and banning the import alone would miss those. src/main.tsx keeps its namespace import -- it republishes the host's React to UMD-bundled plugins, which resolve it through a `React` global.
93 lines
3.4 KiB
JavaScript
93 lines
3.4 KiB
JavaScript
/*!
|
|
* Licensed to the Apache Software Foundation (ASF) under one
|
|
* or more contributor license agreements. See the NOTICE file
|
|
* distributed with this work for additional information
|
|
* regarding copyright ownership. The ASF licenses this file
|
|
* to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance
|
|
* with the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing,
|
|
* software distributed under the License is distributed on an
|
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
* KIND, either express or implied. See the License for the
|
|
* specific language governing permissions and limitations
|
|
* under the License.
|
|
*/
|
|
|
|
import js from "@eslint/js";
|
|
import globals from "globals";
|
|
import perfectionist from "eslint-plugin-perfectionist";
|
|
import reactHooks from "eslint-plugin-react-hooks";
|
|
import reactRefresh from "eslint-plugin-react-refresh";
|
|
import tseslint from "typescript-eslint";
|
|
import prettierConfig from "eslint-config-prettier";
|
|
|
|
export default tseslint.config(
|
|
{ ignores: ["dist"] },
|
|
{
|
|
extends: [js.configs.recommended, ...tseslint.configs.recommended],
|
|
files: ["**/*.{ts,tsx}"],
|
|
languageOptions: {
|
|
ecmaVersion: "latest",
|
|
globals: globals.browser,
|
|
},
|
|
plugins: {
|
|
perfectionist,
|
|
"react-hooks": reactHooks,
|
|
"react-refresh": reactRefresh,
|
|
},
|
|
rules: {
|
|
...reactHooks.configs.recommended.rules,
|
|
// `@types/react` declares `export as namespace React`, so `React.ReactNode`
|
|
// type-checks even without an import — only a syntax rule catches those.
|
|
"@typescript-eslint/no-restricted-imports": [
|
|
"error",
|
|
{
|
|
paths: [
|
|
{
|
|
importNames: ["default"],
|
|
message:
|
|
'The automatic JSX runtime makes the React namespace import unnecessary. Import what you need by name, e.g. `import { forwardRef, type ReactNode } from "react"`.',
|
|
name: "react",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
"no-restricted-syntax": [
|
|
"error",
|
|
{
|
|
message:
|
|
"Do not type components with `React.FC`. Annotate the props parameter instead: `const Foo = ({ bar }: FooProps) => ...`.",
|
|
selector: "TSQualifiedName[left.name='React'][right.name=/^(FC|FunctionComponent|VFC)$/]",
|
|
},
|
|
{
|
|
message:
|
|
"Do not type components with `FC`. Annotate the props parameter instead: `const Foo = ({ bar }: FooProps) => ...`.",
|
|
selector:
|
|
"VariableDeclarator[init.type='ArrowFunctionExpression'] > Identifier > TSTypeAnnotation > TSTypeReference > Identifier[name=/^(FC|FunctionComponent|VFC)$/]",
|
|
},
|
|
{
|
|
message:
|
|
'Import React types by name instead of qualifying them with the `React` namespace: `import { type ReactElement } from "react"`, then use `ReactElement`.',
|
|
selector: "TSQualifiedName[left.name='React']:not([right.name=/^(FC|FunctionComponent|VFC)$/])",
|
|
},
|
|
],
|
|
"perfectionist/sort-objects": [
|
|
"error",
|
|
{
|
|
type: "natural",
|
|
order: "asc",
|
|
},
|
|
],
|
|
"react-refresh/only-export-components": [
|
|
"warn",
|
|
{ allowConstantExport: true },
|
|
],
|
|
},
|
|
},
|
|
prettierConfig
|
|
);
|