【问题标题】:React cannot augment React types configuration with separate fileReact 无法使用单独的文件来增加 React 类型配置
【发布时间】:2022-10-13 02:12:53
【问题描述】:

react 库中有一些类型我尝试通过扩充来重载:

在我的项目中,我创建了一个文件:./@types/react/index.d.ts,内容为:

import type React from 'react';

declare module 'react' {
    function memo<A, B>(Component: (props: A) => B): (props: A) => React.ReactElement | null;
}

我确实解决了我在使用 TypeScript 时遇到的一些问题,这与这个问题无关。

我还在我的./tsconfig.json 文件中提供了这个@types 文件夹:

"typeRoots": ["./node_modules/@types", "./@types"],

但是问题仍然存在(即我的超载不会影响最初的问题)。

如果相反,在我遇到问题的文件中,我只需粘贴代码块:

declare module 'react' {
    function memo<A, B>(Component: (props: A) => B): (props: A) => React.ReactElement | null;
}

...然后问题解决了。

但我宁愿不使用这种方式,内联。 我不希望此声明显示在文件中。

谁能说出为什么@types 文件夹解决方案不起作用?


复制:使用 CRA 样板创建一个虚拟项目:

npx create-react-app whatever --template typescript

修改 ./tsconfig.json 文件内容:

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "typeRoots": [
      "./node_modules/@types",
      "./@types"
    ]  
  },
  "include": [
    "src"
  ]
}

创建 ./@types/react/index.d.ts 文件内容:

declare module "react" { // augment React types
    function memo<A, B>(Component: (props: A) => B): (props: A) => React.ReactElement | null
    // return type is same as ReturnType<ExoticComponent<any>>
  }

创建./src/Filter.tsx 文件:

import React from 'react';

import type { IOption } from './option';

import FilterView from './Filter.view';

interface IProps<T> {
    readonly title: string;
    readonly options: IOption<T>[];
    readonly selectedOption: T;
    readonly onSelectOption: (value: T) => void;
}

const Filter = <T,>(props: React.PropsWithChildren<IProps<T>>) => (
    <FilterView
        title={props.title}
        options={props.options}
        selectedOption={props.selectedOption}
        onSelectOption={props.onSelectOption}
    />
);

Filter.displayName = 'Filter';
Filter.defaultProps = {};

export default React.memo(Filter);

创建Filter.view.tsx 文件:

import React from 'react';

import type { IOption } from './option';

import classes from './Filter.module.scss';

interface IProps<T> {
    readonly title: string;
    readonly options: IOption<T>[];
    readonly selectedOption: T;
    readonly onSelectOption: (value: T) => void;
}

const FilterView = <T,>(props: React.PropsWithChildren<IProps<T>>) => {
    return (
        <div className={classes['container']}>
            <h5 className={classes['container__title']}>{props.title}</h5>

            {props.options.map((option, index) => (
                <button
                    key={index}
                    className={classes['blabla']}
                    type="button"
                    onClick={() => props.onSelectOption(option.value)}
                >
                    {option.label}
                </button>
            ))}
        </div>
    );
};

FilterView.displayName = 'FilterView';
FilterView.defaultProps = {};

export default React.memo(FilterView);

创建./option.ts 文件:

export interface IOption<T> {
    readonly value: T;
    readonly label: string;
}

然后你会在Filter.tsx 文件中看到一个错误。

【问题讨论】:

    标签: reactjs typescript


    【解决方案1】:

    如果你的模块扩充在src/@types/react/index.d.ts,你应该用"./src/@types"(而不是"./@types")填充typeRoots tsconfig 选项:

    "typeRoots": [
        "./node_modules/@types",
        "./src/@types"
    ]
    

    所有路径都相对于tsconfig.json

    注意:导入中有错字:

    import React from 'react'; // React first letter uppercase to match how it is used in the file: React.ReactElement
    

    演示:https://codesandbox.io/s/hopeful-silence-qzu12v?file=/tsconfig.json


    移动全局类型文件后外部您的 ./src 目录,它们不再自动包含在您的 TS 编译中,因为 tsconfig 仅提及该文件夹:

      "include": [
        "src"
      ]
    

    这就是为什么您必须在typeRoots 选项列表中包含新文件夹。

    然而,TS 首先在"./node_modules/@types/react" 中找到了正常的react 类型,并停在那里。我们的扩充文件被遗忘了......

    因此,请确保首先指定您自己的类型根:

    "typeRoots": [
        "./@types", // Own root with augmentations first
        "./node_modules/@types" // base root last
    ]
    

    这样,TS 首先在"./@types/react" 中获取我们的扩充文件。在该文件中,它再次找到import "react",并查找相应的“基本”react 类型定义文件。

    演示:https://codesandbox.io/s/wizardly-shaw-dw84bj?file=/tsconfig.json:519-566

    【讨论】:

    猜你喜欢
    • 2016-07-07
    • 2020-10-18
    • 2018-08-27
    • 1970-01-01
    • 2016-06-03
    • 2021-01-02
    • 1970-01-01
    • 2021-04-17
    • 2020-08-06
    相关资源
    最近更新 更多