typescript не показывает ошибок в пропсах

Рейтинг: 2Ответов: 1Опубликовано: 14.05.2023

Пишу приложение на Vite + Preact + Typescript + Eslint + Prettier

Проблема в том, что typescript не показывает ошибки когда я передаю незадекларированные пропсы. Так же нет ошибок когда я НЕ передаю обязательные пропсы

Компоненты:

interface SidebarProps {
  someNumber: number
  someString: string
}

const Sidebar: React.FC<SidebarProps> = (): JSX.Element => {
  return (
    <nav className="sidebar">
      <div className="item">item 1</div>
      <div className="item">item 2</div>
      <div className="item">item 3</div>
      <div className="item">item 4</div>
    </nav>
  )
}

const App: React.FC = (): JSX.Element => {
  return (
    <div className="app">
      <Sidebar />
    </div>
  )
}


 

vite.config.js

import { defineConfig } from 'vite'
import preact from '@preact/preset-vite'
import path from 'path'
import postcssModules from 'postcss-modules'
import reactRefresh from '@vitejs/plugin-react-refresh'

export default defineConfig({
  plugins: [
    preact(),
    reactRefresh(),
    {
      name: 'postcss-modules',
      async generateBundle(_, bundle) {
        for (const file in bundle) {
          const css = bundle[file].css?.code
          if (css) {
            const { result, exports } = await postcssModules({
              getJSON: (cssFile, json) => {
                const cssFileName = `${path.basename(
                  cssFile,
                  '.css',
                )}.module.css.json`
                bundle[file].source = json
                bundle[file].fileName = cssFileName
              },
            })
            bundle[file].css = {
              code: result,
              modules: exports,
            }
          }
        }
      },
    },
  ],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
      '@components': path.resolve(__dirname, './src/components/'),
      '@layouts': path.resolve(__dirname, './src/layouts/'),
      '@store': path.resolve(__dirname, './src/store/'),
      '@utils': path.resolve(__dirname, './src/utils/'),
      '@icons': path.resolve(__dirname, './src/icons/'),
      '@context': path.resolve(__dirname, './src/context/'),
      '@assets': path.resolve(__dirname, './src/assets/'),
      '@hooks': path.resolve(__dirname, './src/hooks/'),
      '@pages': path.resolve(__dirname, './src/pages/'),
    },
  },
  css: {
    modules: {
      scopeBehaviour: 'local',
      localsConvention: 'camelCaseOnly',
    },
  },
})

tsconfig.json

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": false,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "baseUrl": ".",
    "paths": {
      "@*": ["src/*"],
      "@layouts*": ["src/layouts/*"],
      "@components*": ["src/components/*"],
      "@store*": ["src/store/*"],
      "@utils*": ["src/utils/*"],
      "@icons*": ["src/icons/*"],
      "@context*": ["src/context/*"],
      "@assets*": ["src/assets/*"],
      "@hooks*": ["src/hooks/*"],
      "@pages*": ["src/pages/*"]
    },
    "lib": ["es6", "dom"],
    "jsx": "react"
  },
  "rules": {
    "space-before-function-paren": ["error", {
      "anonymous": "always",
      "named": "never",
      "asyncArrow": "always"
    }]
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "build", "dist"]
}

tsconfig.eslint.json

{
  "compilerOptions": {
    "strict": true,
    "types": ["@types/node"],
    "noEmit": true,
    "allowJs": true
  },
  "extends": "./tsconfig.json",
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx",
    "vite.config.ts"
  ]
}

.eslintrc.json

{
  "extends": [
    "plugin:import/typescript",
    "plugin:prettier/recommended"
  ],
  "plugins": ["@typescript-eslint", "prettier", "react"],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaVersion": 2018,
    "ecmaFeatures": {
      "jsx": true
    },
    "sourceType": "module",
    "project": "./tsconfig.eslint.json",
    "extraFileExtensions": [".ts", ".tsx"]
  },
  "env": {
    "browser": true,
    "es6": true,
    "node": true
  },
  "rules": {
    "prettier/prettier": "error",
    "semi": "off",
    "react/react-in-jsx-scope": ["off"],
    "react/jsx-uses-react": ["off"],
    "react/jsx-props-no-spreading": ["off"],
    "react/no-unescaped-entities": ["off"]
  }
}

.prettierrc

{
  "tabWidth": 2,
  "semi": false,
  "singleQuote": true,
  "trailingComma": "all",
  "printWidth": 80,
  "useTabs": true,
  "endOfLine": "auto"
}

Ответы

▲ 0

В компоненте Sidebar передавать пропсы в качестве параметра функции:

  const Sidebar: React.FC<SidebarProps> = (props): JSX.Element => {
  const { someNumber, someString } = props;

  return (
    <nav className="sidebar">
      <div className="item">item 1</div>
      <div className="item">item 2</div>
      <div className="item">item 3</div>
      <div className="item">item 4</div>
    </nav>
  );
};

В компоненте App передавать необходимые пропсы компоненту Sidebar:

const App: React.FC = (): JSX.Element => {
  return (
    <div className="app">
      <Sidebar someNumber={42} someString="Hello" /> // в качестве примера
    </div>
  );
};

В файле tsconfig.json установите "strictNullChecks": true. Это позволит TypeScript проверять наличие обязательных пропсов:

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "strict": true,
    "strictNullChecks": true,
    "esModuleInterop": true,
    "skipLibCheck": false,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "baseUrl": ".",
    "paths": {
      // ...
    },
    "lib": ["es6", "dom"],
    "jsx": "react"
  },
  "rules": {
    "space-before-function-paren": ["error", {
      "anonymous": "always",
      "named": "never",
      "asyncArrow": "always"
    }]
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "build", "dist"]
}

В файле .eslintrc.json "@typescript-eslint/explicit-module-boundary-types": "off", чтобы избежать предупреждения о явном указании типа в возвращаемых значениях функций:

{
  "extends": [
    "plugin:import/typescript",
    "plugin:prettier/recommended"
  ],
  "plugins": ["@typescript-eslint", "prettier", "react"],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaVersion": 2018,
    "ecmaFeatures": {
      "jsx": true
    },
    "sourceType": "module",
    "project": "./tsconfig.eslint.json",
    "extraFileExtensions": [".ts", ".tsx"]
  },
  "env": {
    "browser": true,
    "es6": true,
    "node": true
  },
  "rules": {
    "prettier/prettier": "error",
    "semi": "off",
    "react/react-in-jsx-scope": ["off"],
    "react/jsx-uses-react": ["off"],
    "react/jsx-props-no-spreading": ["off"],
    "react/no-unescaped-entities": ["off"],
    "@typescript-eslint/explicit-module-boundary-types": "off"
  }
}

Ну и установите необходимые пакеты, если они отсутствуют. Кеп Очевидность ))