There is some type in react library I try to overload with an augmentation:
In my project, I created a file: ./@types/react/index.d.ts, with content:
import type React from 'react';
declare module 'react' {
function memo<A, B>(Component: (props: A) => B): (props: A) => React.ReactElement | null;
}
I did to solve some issue I had with TypeScript, which is irrelevant for this question.
I have also provided this @types folder in my ./tsconfig.json file:
"typeRoots": ["./node_modules/@types", "./@types"],
But issue still shows (i.e. my overload does not affect the initial issue).
If instead, in the file I had the issue, I just paste the code block:
declare module 'react' {
function memo<A, B>(Component: (props: A) => B): (props: A) => React.ReactElement | null;
}
...then issue is resolved.
But I rather not use this way, inline-like. I don't want this declaration to show in the file.
Could anyone tell why the @types folder solution does not work?
Reproduce: Create a dummy project with boilerplate of CRA:
npx create-react-app whatever --template typescript
Modify ./tsconfig.json file with content:
{
"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"
]
}
Create ./@types/react/index.d.ts file with content:
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>>
}
Create ./src/Filter.tsx file:
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);
Create Filter.view.tsx file:
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);
Create ./option.ts file:
export interface IOption<T> {
readonly value: T;
readonly label: string;
}
Then you'll see an error in Filter.tsx file.