diff --git a/packages/docusaurus-types/package.json b/packages/docusaurus-types/package.json index f88cdcdb1958..a029043b5181 100644 --- a/packages/docusaurus-types/package.json +++ b/packages/docusaurus-types/package.json @@ -14,6 +14,7 @@ "license": "MIT", "dependencies": { "@types/history": "^4.7.11", + "@types/react": "*", "commander": "^5.1.0", "joi": "^17.6.0", "react-helmet-async": "^1.3.0", diff --git a/packages/docusaurus-types/src/index.d.ts b/packages/docusaurus-types/src/index.d.ts index 2cae26753d5b..ced9b8bf6fe1 100644 --- a/packages/docusaurus-types/src/index.d.ts +++ b/packages/docusaurus-types/src/index.d.ts @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. */ +import type {JSXElementConstructor} from 'react'; import type {RuleSetRule, Configuration as WebpackConfiguration} from 'webpack'; import type {CustomizeRuleString} from 'webpack-merge/dist/types'; import type {CommanderStatic} from 'commander'; @@ -758,3 +759,24 @@ export type UseDataOptions = { */ failfast?: boolean; }; + +/** + * This type is almost the same as `React.ComponentProps`, but with one minor + * fix: when the component is a function with no parameters, it produces `{}` + * instead of `unknown`, allowing us to spread the props derived from another + * component. This is useful for wrap swizzling. + * + * @see https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/60766 + */ +export type WrapperProps< + // eslint-disable-next-line @typescript-eslint/no-explicit-any + T extends keyof JSX.IntrinsicElements | JSXElementConstructor, +> = T extends JSXElementConstructor + ? unknown extends P + ? // eslint-disable-next-line @typescript-eslint/ban-types + {} + : P + : T extends keyof JSX.IntrinsicElements + ? JSX.IntrinsicElements[T] + : // eslint-disable-next-line @typescript-eslint/ban-types + {}; diff --git a/packages/docusaurus/src/commands/swizzle/__tests__/__snapshots__/actions.test.ts.snap b/packages/docusaurus/src/commands/swizzle/__tests__/__snapshots__/actions.test.ts.snap index 36fc80b4478f..a6aa55acc13b 100644 --- a/packages/docusaurus/src/commands/swizzle/__tests__/__snapshots__/actions.test.ts.snap +++ b/packages/docusaurus/src/commands/swizzle/__tests__/__snapshots__/actions.test.ts.snap @@ -43,14 +43,12 @@ export default function FirstLevelComponentWrapper(props) { `; exports[`wrap TypeScript wrap ComponentInFolder 2`] = ` -"import React, {ComponentProps} from 'react'; +"import React from 'react'; import ComponentInFolder from '@theme-original/ComponentInFolder'; import type ComponentInFolderType from '@theme/ComponentInFolder'; +import type {WrapperProps} from '@docusaurus/types'; -type RawProps = ComponentProps; -// ComponentProps is a little buggy, quick fix. -// https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/60766 -type Props = unknown extends RawProps ? {} : RawProps; +type Props = WrapperProps; export default function ComponentInFolderWrapper(props: Props): JSX.Element { return ( @@ -63,14 +61,12 @@ export default function ComponentInFolderWrapper(props: Props): JSX.Element { `; exports[`wrap TypeScript wrap ComponentInFolder/ComponentInSubFolder 2`] = ` -"import React, {ComponentProps} from 'react'; +"import React from 'react'; import ComponentInSubFolder from '@theme-original/ComponentInFolder/ComponentInSubFolder'; import type ComponentInSubFolderType from '@theme/ComponentInFolder/ComponentInSubFolder'; +import type {WrapperProps} from '@docusaurus/types'; -type RawProps = ComponentProps; -// ComponentProps is a little buggy, quick fix. -// https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/60766 -type Props = unknown extends RawProps ? {} : RawProps; +type Props = WrapperProps; export default function ComponentInSubFolderWrapper(props: Props): JSX.Element { return ( @@ -83,14 +79,12 @@ export default function ComponentInSubFolderWrapper(props: Props): JSX.Element { `; exports[`wrap TypeScript wrap FirstLevelComponent 2`] = ` -"import React, {ComponentProps} from 'react'; +"import React from 'react'; import FirstLevelComponent from '@theme-original/FirstLevelComponent'; import type FirstLevelComponentType from '@theme/FirstLevelComponent'; +import type {WrapperProps} from '@docusaurus/types'; -type RawProps = ComponentProps; -// ComponentProps is a little buggy, quick fix. -// https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/60766 -type Props = unknown extends RawProps ? {} : RawProps; +type Props = WrapperProps; export default function FirstLevelComponentWrapper(props: Props): JSX.Element { return ( diff --git a/packages/docusaurus/src/commands/swizzle/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus/src/commands/swizzle/__tests__/__snapshots__/index.test.ts.snap index e1d28fc40529..31fa888fe07c 100644 --- a/packages/docusaurus/src/commands/swizzle/__tests__/__snapshots__/index.test.ts.snap +++ b/packages/docusaurus/src/commands/swizzle/__tests__/__snapshots__/index.test.ts.snap @@ -273,14 +273,12 @@ exports[`swizzle wrap ComponentInFolder JS: theme dir tree 1`] = ` `; exports[`swizzle wrap ComponentInFolder TS: ComponentInFolder/index.tsx 1`] = ` -"import React, {ComponentProps} from 'react'; +"import React from 'react'; import ComponentInFolder from '@theme-original/ComponentInFolder'; import type ComponentInFolderType from '@theme/ComponentInFolder'; +import type {WrapperProps} from '@docusaurus/types'; -type RawProps = ComponentProps; -// ComponentProps is a little buggy, quick fix. -// https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/60766 -type Props = unknown extends RawProps ? {} : RawProps; +type Props = WrapperProps; export default function ComponentInFolderWrapper(props: Props): JSX.Element { return ( @@ -320,14 +318,12 @@ exports[`swizzle wrap ComponentInFolder/ComponentInSubFolder JS: theme dir tree `; exports[`swizzle wrap ComponentInFolder/ComponentInSubFolder TS: ComponentInFolder/ComponentInSubFolder/index.tsx 1`] = ` -"import React, {ComponentProps} from 'react'; +"import React from 'react'; import ComponentInSubFolder from '@theme-original/ComponentInFolder/ComponentInSubFolder'; import type ComponentInSubFolderType from '@theme/ComponentInFolder/ComponentInSubFolder'; +import type {WrapperProps} from '@docusaurus/types'; -type RawProps = ComponentProps; -// ComponentProps is a little buggy, quick fix. -// https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/60766 -type Props = unknown extends RawProps ? {} : RawProps; +type Props = WrapperProps; export default function ComponentInSubFolderWrapper(props: Props): JSX.Element { return ( @@ -367,14 +363,12 @@ exports[`swizzle wrap ComponentInFolder/Sibling JS: theme dir tree 1`] = ` `; exports[`swizzle wrap ComponentInFolder/Sibling TS: ComponentInFolder/Sibling.tsx 1`] = ` -"import React, {ComponentProps} from 'react'; +"import React from 'react'; import Sibling from '@theme-original/ComponentInFolder/Sibling'; import type SiblingType from '@theme/ComponentInFolder/Sibling'; +import type {WrapperProps} from '@docusaurus/types'; -type RawProps = ComponentProps; -// ComponentProps is a little buggy, quick fix. -// https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/60766 -type Props = unknown extends RawProps ? {} : RawProps; +type Props = WrapperProps; export default function SiblingWrapper(props: Props): JSX.Element { return ( @@ -412,14 +406,12 @@ exports[`swizzle wrap FirstLevelComponent JS: theme dir tree 1`] = ` `; exports[`swizzle wrap FirstLevelComponent TS: FirstLevelComponent.tsx 1`] = ` -"import React, {ComponentProps} from 'react'; +"import React from 'react'; import FirstLevelComponent from '@theme-original/FirstLevelComponent'; import type FirstLevelComponentType from '@theme/FirstLevelComponent'; +import type {WrapperProps} from '@docusaurus/types'; -type RawProps = ComponentProps; -// ComponentProps is a little buggy, quick fix. -// https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/60766 -type Props = unknown extends RawProps ? {} : RawProps; +type Props = WrapperProps; export default function FirstLevelComponentWrapper(props: Props): JSX.Element { return ( diff --git a/packages/docusaurus/src/commands/swizzle/actions.ts b/packages/docusaurus/src/commands/swizzle/actions.ts index 548de7aedf98..3bc38febcd75 100644 --- a/packages/docusaurus/src/commands/swizzle/actions.ts +++ b/packages/docusaurus/src/commands/swizzle/actions.ts @@ -121,14 +121,12 @@ export async function wrap({ const toPath = path.resolve(siteDir, THEME_PATH, wrapperFileName); const content = typescript - ? `import React, {ComponentProps} from 'react'; + ? `import React from 'react'; import ${componentName} from '@theme-${importType}/${themeComponentName}'; import type ${componentName}Type from '@theme/${themeComponentName}'; +import type {WrapperProps} from '@docusaurus/types'; -type RawProps = ComponentProps; -// ComponentProps is a little buggy, quick fix. -// https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/60766 -type Props = unknown extends RawProps ? {} : RawProps; +type Props = WrapperProps; export default function ${wrapperComponentName}(props: Props): JSX.Element { return (