From 5002ce51d7ad9082f1066f5cadcb2ef23811f779 Mon Sep 17 00:00:00 2001 From: David Cho-Lerat Date: Tue, 21 Nov 2023 09:28:45 +0100 Subject: [PATCH] SONAR-21017 TypeScript: the `children` prop must now be explicit (see https://react.dev/blog/2022/03/08/react-18-upgrade-guide#updates-to-typescript-definitions) --- .../design-system/src/components/FacetBox.tsx | 2 +- .../src/components/FavoriteButton.tsx | 2 +- .../src/components/InteractiveIcon.tsx | 18 +++++++++++++----- .../design-system/src/components/Tags.tsx | 2 +- .../design-system/src/components/Tooltip.tsx | 2 +- .../src/components/avatar/GenericAvatar.tsx | 2 +- .../src/components/buttons/ButtonPrimary.tsx | 2 +- .../src/components/buttons/ButtonSecondary.tsx | 2 +- .../components/buttons/DangerButtonPrimary.tsx | 2 +- .../buttons/DangerButtonSecondary.tsx | 2 +- .../components/buttons/ThirdPartyButton.tsx | 2 +- .../src/components/buttons/WrapperButton.tsx | 2 +- .../design-system/src/components/clipboard.tsx | 2 +- .../src/components/icons/Icon.tsx | 6 +++--- .../design-system/src/theme/withTheme.tsx | 4 ++-- .../sonar-web/design-system/src/types/misc.ts | 3 ++- .../src/main/js/app/components/PageTracker.tsx | 2 +- .../main/js/app/components/StartupModal.tsx | 2 +- .../admin/withAdminPagesOutletContext.tsx | 4 +++- .../app-state/withAppStateContext.tsx | 4 +++- .../withAvailableFeatures.tsx | 4 +++- .../componentContext/withComponentContext.tsx | 2 +- .../CurrentUserContextProvider.tsx | 5 ++++- .../current-user/withCurrentUserContext.tsx | 6 +++++- .../languages/LanguagesContextProvider.tsx | 5 ++++- .../languages/withLanguagesContext.tsx | 4 +++- .../metrics/MetricsContextProvider.tsx | 5 ++++- .../components/metrics/withMetricsContext.tsx | 4 +++- .../qualityProfilesContext.tsx | 15 +++++++++------ .../apps/settings/components/inputs/Input.tsx | 4 +++- .../components/inputs/InputForSecured.tsx | 4 +++- .../components/inputs/PrimitiveInput.tsx | 10 ++++++++-- .../main/js/components/a11y/A11yProvider.tsx | 2 +- .../src/main/js/components/controls/Radio.tsx | 2 +- .../main/js/components/controls/Tooltip.tsx | 2 +- .../embed-docs-modal/SuggestionsProvider.tsx | 2 +- .../src/main/js/components/hoc/utils.ts | 2 +- .../main/js/components/hoc/whenLoggedIn.tsx | 4 +++- .../js/components/hoc/withCLanguageFeature.tsx | 4 +++- .../components/hoc/withIndexationContext.tsx | 4 +++- .../js/components/hoc/withIndexationGuard.tsx | 2 +- .../components/hoc/withKeyboardNavigation.tsx | 4 +++- .../main/js/components/hoc/withLocation.tsx | 4 +++- .../js/components/hoc/withNotifications.tsx | 4 +++- .../src/main/js/components/hoc/withRouter.tsx | 13 +++++++------ .../main/js/components/hoc/withScrollTo.tsx | 8 ++++++-- .../js/components/icons/ProjectLinkIcon.tsx | 4 +++- .../js/components/permissions/HoldersList.tsx | 5 ++++- .../rules/MoreInfoRuleDescription.tsx | 4 +++- .../tutorials/jenkins/JenkinsStep.tsx | 4 +++- .../src/main/js/components/ui/popups.tsx | 2 +- .../main/js/components/workspace/Workspace.tsx | 2 +- .../components/workspace/WorkspaceHeader.tsx | 2 +- .../components/workspace/WorkspacePortal.tsx | 2 +- .../sonar-web/src/main/js/helpers/testUtils.ts | 11 +++++++++-- .../sonar-web/src/main/js/queries/branch.tsx | 16 +++++++++++++--- server/sonar-web/src/main/js/types/misc.ts | 3 ++- 57 files changed, 168 insertions(+), 79 deletions(-) diff --git a/server/sonar-web/design-system/src/components/FacetBox.tsx b/server/sonar-web/design-system/src/components/FacetBox.tsx index 302799edf9d..08a6e4ec2c1 100644 --- a/server/sonar-web/design-system/src/components/FacetBox.tsx +++ b/server/sonar-web/design-system/src/components/FacetBox.tsx @@ -51,7 +51,7 @@ export interface FacetBoxProps { onClear?: () => void; onClick?: (isOpen: boolean) => void; open?: boolean; - tooltipComponent?: React.ComponentType<{ overlay: React.ReactNode }>; + tooltipComponent?: React.ComponentType>; } export function FacetBox(props: FacetBoxProps) { diff --git a/server/sonar-web/design-system/src/components/FavoriteButton.tsx b/server/sonar-web/design-system/src/components/FavoriteButton.tsx index 10c8f717c04..9b822c087e5 100644 --- a/server/sonar-web/design-system/src/components/FavoriteButton.tsx +++ b/server/sonar-web/design-system/src/components/FavoriteButton.tsx @@ -28,7 +28,7 @@ interface Props { innerRef?: React.Ref; overlay: string; toggleFavorite: VoidFunction; - tooltip?: React.ComponentType<{ overlay: React.ReactNode }>; + tooltip?: React.ComponentType>; } export function FavoriteButton(props: Props) { diff --git a/server/sonar-web/design-system/src/components/InteractiveIcon.tsx b/server/sonar-web/design-system/src/components/InteractiveIcon.tsx index 00fee474192..f00a59a6f64 100644 --- a/server/sonar-web/design-system/src/components/InteractiveIcon.tsx +++ b/server/sonar-web/design-system/src/components/InteractiveIcon.tsx @@ -33,7 +33,7 @@ import { IconProps } from './icons/Icon'; export type InteractiveIconSize = 'small' | 'medium'; export interface InteractiveIconProps { - Icon: React.ComponentType; + Icon: React.ComponentType>; 'aria-label': string; children?: React.ReactNode; className?: string; @@ -147,7 +147,9 @@ const IconButton = styled.button` ${buttonIconStyle} `; -export const InteractiveIcon: React.FC = styled(InteractiveIconBase)` +export const InteractiveIcon: React.FC> = styled( + InteractiveIconBase, +)` --background: ${themeColor('interactiveIcon')}; --backgroundHover: ${themeColor('interactiveIconHover')}; --color: ${({ currentColor, theme }) => @@ -156,11 +158,15 @@ export const InteractiveIcon: React.FC = styled(Interactiv --focus: ${themeColor('interactiveIconFocus', OPACITY_20_PERCENT)}; `; -export const DiscreetInteractiveIcon: React.FC = styled(InteractiveIcon)` +export const DiscreetInteractiveIcon: React.FC< + React.PropsWithChildren +> = styled(InteractiveIcon)` --color: ${themeColor('discreetInteractiveIcon')}; `; -export const DestructiveIcon: React.FC = styled(InteractiveIconBase)` +export const DestructiveIcon: React.FC> = styled( + InteractiveIconBase, +)` --background: ${themeColor('destructiveIcon')}; --backgroundHover: ${themeColor('destructiveIconHover')}; --color: ${themeContrast('destructiveIcon')}; @@ -168,7 +174,9 @@ export const DestructiveIcon: React.FC = styled(Interactiv --focus: ${themeColor('destructiveIconFocus', OPACITY_20_PERCENT)}; `; -export const DismissProductNewsIcon: React.FC = styled(InteractiveIcon)` +export const DismissProductNewsIcon: React.FC< + React.PropsWithChildren +> = styled(InteractiveIcon)` --background: ${themeColor('productNews')}; --backgroundHover: ${themeColor('productNewsHover')}; --color: ${themeContrast('productNews')}; diff --git a/server/sonar-web/design-system/src/components/Tags.tsx b/server/sonar-web/design-system/src/components/Tags.tsx index 88c613bc9a9..200415cfb65 100644 --- a/server/sonar-web/design-system/src/components/Tags.tsx +++ b/server/sonar-web/design-system/src/components/Tags.tsx @@ -39,7 +39,7 @@ interface Props { popupPlacement?: PopupPlacement; tags: string[]; tagsToDisplay?: number; - tooltip?: React.ComponentType<{ overlay: React.ReactNode }>; + tooltip?: React.ComponentType>; } export function Tags({ diff --git a/server/sonar-web/design-system/src/components/Tooltip.tsx b/server/sonar-web/design-system/src/components/Tooltip.tsx index 209a8fdddd2..1b5a763dec2 100644 --- a/server/sonar-web/design-system/src/components/Tooltip.tsx +++ b/server/sonar-web/design-system/src/components/Tooltip.tsx @@ -401,7 +401,7 @@ export class TooltipInner extends React.Component { } } -class TooltipPortal extends React.Component { +class TooltipPortal extends React.Component { el: HTMLElement; constructor(props: object) { diff --git a/server/sonar-web/design-system/src/components/avatar/GenericAvatar.tsx b/server/sonar-web/design-system/src/components/avatar/GenericAvatar.tsx index 2590ccbefdb..2125141e367 100644 --- a/server/sonar-web/design-system/src/components/avatar/GenericAvatar.tsx +++ b/server/sonar-web/design-system/src/components/avatar/GenericAvatar.tsx @@ -26,7 +26,7 @@ import { IconProps } from '../icons/Icon'; import { Size, iconSizeMap, sizeMap } from './utils'; export interface GenericAvatarProps { - Icon?: React.ComponentType; + Icon?: React.ComponentType>; className?: string; name: string; size?: Size; diff --git a/server/sonar-web/design-system/src/components/buttons/ButtonPrimary.tsx b/server/sonar-web/design-system/src/components/buttons/ButtonPrimary.tsx index 6550e5c6588..0b3365667a7 100644 --- a/server/sonar-web/design-system/src/components/buttons/ButtonPrimary.tsx +++ b/server/sonar-web/design-system/src/components/buttons/ButtonPrimary.tsx @@ -32,6 +32,6 @@ export const PrimaryStyle = (props: ThemedProps) => css` --border: ${themeBorder('default', 'transparent')(props)}; `; -export const ButtonPrimary: React.FC = styled(Button)` +export const ButtonPrimary: React.FC> = styled(Button)` ${PrimaryStyle} `; diff --git a/server/sonar-web/design-system/src/components/buttons/ButtonSecondary.tsx b/server/sonar-web/design-system/src/components/buttons/ButtonSecondary.tsx index 8769d3f4052..09ad0b73bfe 100644 --- a/server/sonar-web/design-system/src/components/buttons/ButtonSecondary.tsx +++ b/server/sonar-web/design-system/src/components/buttons/ButtonSecondary.tsx @@ -21,7 +21,7 @@ import styled from '@emotion/styled'; import { OPACITY_20_PERCENT, themeBorder, themeColor, themeContrast } from '../../helpers'; import { Button, ButtonProps } from './Button'; -export const ButtonSecondary: React.FC = styled(Button)` +export const ButtonSecondary: React.FC> = styled(Button)` --background: ${themeColor('buttonSecondary')}; --backgroundHover: ${themeColor('buttonSecondaryHover')}; --color: ${themeContrast('buttonSecondary')}; diff --git a/server/sonar-web/design-system/src/components/buttons/DangerButtonPrimary.tsx b/server/sonar-web/design-system/src/components/buttons/DangerButtonPrimary.tsx index d954a539dfa..6fc7d558977 100644 --- a/server/sonar-web/design-system/src/components/buttons/DangerButtonPrimary.tsx +++ b/server/sonar-web/design-system/src/components/buttons/DangerButtonPrimary.tsx @@ -22,7 +22,7 @@ import styled from '@emotion/styled'; import { OPACITY_20_PERCENT, themeBorder, themeColor, themeContrast } from '../../helpers'; import { Button, ButtonProps } from './Button'; -export const DangerButtonPrimary: React.FC = styled(Button)` +export const DangerButtonPrimary: React.FC> = styled(Button)` --background: ${themeColor('dangerButton')}; --backgroundHover: ${themeColor('dangerButtonHover')}; --color: ${themeContrast('dangerButton')}; diff --git a/server/sonar-web/design-system/src/components/buttons/DangerButtonSecondary.tsx b/server/sonar-web/design-system/src/components/buttons/DangerButtonSecondary.tsx index 0decc1751b3..02768ad8de8 100644 --- a/server/sonar-web/design-system/src/components/buttons/DangerButtonSecondary.tsx +++ b/server/sonar-web/design-system/src/components/buttons/DangerButtonSecondary.tsx @@ -22,7 +22,7 @@ import styled from '@emotion/styled'; import { OPACITY_20_PERCENT, themeBorder, themeColor, themeContrast } from '../../helpers'; import { Button, ButtonProps } from './Button'; -export const DangerButtonSecondary: React.FC = styled(Button)` +export const DangerButtonSecondary: React.FC> = styled(Button)` --background: ${themeColor('dangerButtonSecondary')}; --backgroundHover: ${themeColor('dangerButtonSecondaryHover')}; --color: ${themeContrast('dangerButtonSecondary')}; diff --git a/server/sonar-web/design-system/src/components/buttons/ThirdPartyButton.tsx b/server/sonar-web/design-system/src/components/buttons/ThirdPartyButton.tsx index 86a9e0b54ac..9f958e79f45 100644 --- a/server/sonar-web/design-system/src/components/buttons/ThirdPartyButton.tsx +++ b/server/sonar-web/design-system/src/components/buttons/ThirdPartyButton.tsx @@ -39,7 +39,7 @@ export function ThirdPartyButton({ children, iconPath, name, ...buttonProps }: T ); } -const ThirdPartyButtonStyled: React.FC = styled(Button)` +const ThirdPartyButtonStyled: React.FC> = styled(Button)` --background: ${themeColor('thirdPartyButton')}; --backgroundHover: ${themeColor('thirdPartyButtonHover')}; --color: ${themeContrast('thirdPartyButton')}; diff --git a/server/sonar-web/design-system/src/components/buttons/WrapperButton.tsx b/server/sonar-web/design-system/src/components/buttons/WrapperButton.tsx index 64d86fc613f..9097c6efe88 100644 --- a/server/sonar-web/design-system/src/components/buttons/WrapperButton.tsx +++ b/server/sonar-web/design-system/src/components/buttons/WrapperButton.tsx @@ -22,7 +22,7 @@ import styled from '@emotion/styled'; import { OPACITY_20_PERCENT, themeColor } from '../../helpers'; import { Button, ButtonProps } from './Button'; -export const WrapperButton: React.FC = styled(Button)` +export const WrapperButton: React.FC> = styled(Button)` --background: none; --backgroundHover: none; --color: none; diff --git a/server/sonar-web/design-system/src/components/clipboard.tsx b/server/sonar-web/design-system/src/components/clipboard.tsx index 460a8bf803e..0bb5155d742 100644 --- a/server/sonar-web/design-system/src/components/clipboard.tsx +++ b/server/sonar-web/design-system/src/components/clipboard.tsx @@ -133,7 +133,7 @@ export function ClipboardButton({ } interface IconButtonProps { - Icon?: React.ComponentType; + Icon?: React.ComponentType>; 'aria-label'?: string; className?: string; copiedLabel?: string; diff --git a/server/sonar-web/design-system/src/components/icons/Icon.tsx b/server/sonar-web/design-system/src/components/icons/Icon.tsx index 58b03f1aa65..5acfd4ee05c 100644 --- a/server/sonar-web/design-system/src/components/icons/Icon.tsx +++ b/server/sonar-web/design-system/src/components/icons/Icon.tsx @@ -87,9 +87,9 @@ export function CustomIcon(props: Props) { } export function OcticonHoc( - WrappedOcticon: React.ComponentType, - displayName?: string -): React.ComponentType { + WrappedOcticon: React.ComponentType>, + displayName?: string, +): React.ComponentType> { function IconWrapper({ fill, ...props }: IconProps) { const theme = useTheme(); diff --git a/server/sonar-web/design-system/src/theme/withTheme.tsx b/server/sonar-web/design-system/src/theme/withTheme.tsx index 64e657fc57e..07713660df1 100644 --- a/server/sonar-web/design-system/src/theme/withTheme.tsx +++ b/server/sonar-web/design-system/src/theme/withTheme.tsx @@ -26,8 +26,8 @@ export interface ThemeProp { } export function withTheme

( - WrappedComponent: React.ComponentType

-): React.ComponentType

{ + WrappedComponent: React.ComponentType>, +): React.ComponentType> { return function WrappedComponentWithTheme(props: P) { const theme = useTheme(); diff --git a/server/sonar-web/design-system/src/types/misc.ts b/server/sonar-web/design-system/src/types/misc.ts index ea95b30ffc6..84faf6ffa49 100644 --- a/server/sonar-web/design-system/src/types/misc.ts +++ b/server/sonar-web/design-system/src/types/misc.ts @@ -18,4 +18,5 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -export type FCProps> = Parameters[0]; +export type FCProps>> = + Parameters[0]; diff --git a/server/sonar-web/src/main/js/app/components/PageTracker.tsx b/server/sonar-web/src/main/js/app/components/PageTracker.tsx index 0bbd94b90ff..d99bc293d94 100644 --- a/server/sonar-web/src/main/js/app/components/PageTracker.tsx +++ b/server/sonar-web/src/main/js/app/components/PageTracker.tsx @@ -35,7 +35,7 @@ interface State { lastLocation?: string; } -export class PageTracker extends React.Component { +export class PageTracker extends React.Component, State> { state: State = {}; componentDidMount() { diff --git a/server/sonar-web/src/main/js/app/components/StartupModal.tsx b/server/sonar-web/src/main/js/app/components/StartupModal.tsx index 80b283d2331..6acaa6e8bbe 100644 --- a/server/sonar-web/src/main/js/app/components/StartupModal.tsx +++ b/server/sonar-web/src/main/js/app/components/StartupModal.tsx @@ -41,7 +41,7 @@ interface State { const LICENSE_PROMPT = 'sonarqube.license.prompt'; -export class StartupModal extends React.PureComponent { +export class StartupModal extends React.PureComponent, State> { state: State = {}; componentDidMount() { diff --git a/server/sonar-web/src/main/js/app/components/admin/withAdminPagesOutletContext.tsx b/server/sonar-web/src/main/js/app/components/admin/withAdminPagesOutletContext.tsx index b241258efb5..b5d3da6ff84 100644 --- a/server/sonar-web/src/main/js/app/components/admin/withAdminPagesOutletContext.tsx +++ b/server/sonar-web/src/main/js/app/components/admin/withAdminPagesOutletContext.tsx @@ -22,7 +22,9 @@ import { useOutletContext } from 'react-router-dom'; import { AdminPagesContext } from '../../../types/admin'; export default function withAdminPagesOutletContext( - WrappedComponent: React.ComponentType, + WrappedComponent: React.ComponentType< + React.PropsWithChildren> + >, ) { return function WithAdminPagesOutletContext() { const { adminPages } = useOutletContext(); diff --git a/server/sonar-web/src/main/js/app/components/app-state/withAppStateContext.tsx b/server/sonar-web/src/main/js/app/components/app-state/withAppStateContext.tsx index 1dc86de5a8c..5a0b13d06af 100644 --- a/server/sonar-web/src/main/js/app/components/app-state/withAppStateContext.tsx +++ b/server/sonar-web/src/main/js/app/components/app-state/withAppStateContext.tsx @@ -27,7 +27,9 @@ export interface WithAppStateContextProps { } export default function withAppStateContext

( - WrappedComponent: React.ComponentType

, + WrappedComponent: React.ComponentType< + React.PropsWithChildren> + >, ) { return class WithAppStateContext extends React.PureComponent< Omit diff --git a/server/sonar-web/src/main/js/app/components/available-features/withAvailableFeatures.tsx b/server/sonar-web/src/main/js/app/components/available-features/withAvailableFeatures.tsx index d81dc252fd0..bc6fdc07173 100644 --- a/server/sonar-web/src/main/js/app/components/available-features/withAvailableFeatures.tsx +++ b/server/sonar-web/src/main/js/app/components/available-features/withAvailableFeatures.tsx @@ -27,7 +27,9 @@ export interface WithAvailableFeaturesProps { } export default function withAvailableFeatures

( - WrappedComponent: React.ComponentType

, + WrappedComponent: React.ComponentType< + React.PropsWithChildren> + >, ) { return class WithAvailableFeatures extends React.PureComponent< Omit diff --git a/server/sonar-web/src/main/js/app/components/componentContext/withComponentContext.tsx b/server/sonar-web/src/main/js/app/components/componentContext/withComponentContext.tsx index 8d5049869d9..122706e9f63 100644 --- a/server/sonar-web/src/main/js/app/components/componentContext/withComponentContext.tsx +++ b/server/sonar-web/src/main/js/app/components/componentContext/withComponentContext.tsx @@ -23,7 +23,7 @@ import { ComponentContextShape } from '../../../types/component'; import { ComponentContext } from './ComponentContext'; export default function withComponentContext

>( - WrappedComponent: React.ComponentType

, + WrappedComponent: React.ComponentType>>, ) { return class WithComponentContext extends React.PureComponent< Omit diff --git a/server/sonar-web/src/main/js/app/components/current-user/CurrentUserContextProvider.tsx b/server/sonar-web/src/main/js/app/components/current-user/CurrentUserContextProvider.tsx index 7408d4fdd36..b726c161d25 100644 --- a/server/sonar-web/src/main/js/app/components/current-user/CurrentUserContextProvider.tsx +++ b/server/sonar-web/src/main/js/app/components/current-user/CurrentUserContextProvider.tsx @@ -29,7 +29,10 @@ interface State { currentUser: CurrentUser; } -export default class CurrentUserContextProvider extends React.PureComponent { +export default class CurrentUserContextProvider extends React.PureComponent< + React.PropsWithChildren, + State +> { constructor(props: Props) { super(props); this.state = { currentUser: props.currentUser ?? { isLoggedIn: false, dismissedNotices: {} } }; diff --git a/server/sonar-web/src/main/js/app/components/current-user/withCurrentUserContext.tsx b/server/sonar-web/src/main/js/app/components/current-user/withCurrentUserContext.tsx index c3695f1f88e..e3cebd7f13a 100644 --- a/server/sonar-web/src/main/js/app/components/current-user/withCurrentUserContext.tsx +++ b/server/sonar-web/src/main/js/app/components/current-user/withCurrentUserContext.tsx @@ -22,7 +22,11 @@ import { getWrappedDisplayName } from '../../../components/hoc/utils'; import { CurrentUserContext, CurrentUserContextInterface } from './CurrentUserContext'; export default function withCurrentUserContext

( - WrappedComponent: React.ComponentType

>, + WrappedComponent: React.ComponentType< + React.PropsWithChildren< + React.PropsWithChildren

> + > + >, ) { return class WithCurrentUserContext extends React.PureComponent< Omit diff --git a/server/sonar-web/src/main/js/app/components/languages/LanguagesContextProvider.tsx b/server/sonar-web/src/main/js/app/components/languages/LanguagesContextProvider.tsx index 9e5d6f5dc13..4275dac2309 100644 --- a/server/sonar-web/src/main/js/app/components/languages/LanguagesContextProvider.tsx +++ b/server/sonar-web/src/main/js/app/components/languages/LanguagesContextProvider.tsx @@ -27,7 +27,10 @@ interface State { languages: Languages; } -export default class LanguagesContextProvider extends React.PureComponent<{}, State> { +export default class LanguagesContextProvider extends React.PureComponent< + React.PropsWithChildren, + State +> { mounted = false; state: State = { languages: {}, diff --git a/server/sonar-web/src/main/js/app/components/languages/withLanguagesContext.tsx b/server/sonar-web/src/main/js/app/components/languages/withLanguagesContext.tsx index f12107b3a52..6b2324f4d24 100644 --- a/server/sonar-web/src/main/js/app/components/languages/withLanguagesContext.tsx +++ b/server/sonar-web/src/main/js/app/components/languages/withLanguagesContext.tsx @@ -27,7 +27,9 @@ export interface WithLanguagesContextProps { } export default function withLanguagesContext

( - WrappedComponent: React.ComponentType

, + WrappedComponent: React.ComponentType< + React.PropsWithChildren> + >, ) { return class WithLanguagesContext extends React.PureComponent< Omit diff --git a/server/sonar-web/src/main/js/app/components/metrics/MetricsContextProvider.tsx b/server/sonar-web/src/main/js/app/components/metrics/MetricsContextProvider.tsx index 529328f7b50..8f64c67bfda 100644 --- a/server/sonar-web/src/main/js/app/components/metrics/MetricsContextProvider.tsx +++ b/server/sonar-web/src/main/js/app/components/metrics/MetricsContextProvider.tsx @@ -27,7 +27,10 @@ interface State { metrics: Dict; } -export default class MetricsContextProvider extends React.PureComponent<{}, State> { +export default class MetricsContextProvider extends React.PureComponent< + React.PropsWithChildren, + State +> { mounted = false; state: State = { metrics: {}, diff --git a/server/sonar-web/src/main/js/app/components/metrics/withMetricsContext.tsx b/server/sonar-web/src/main/js/app/components/metrics/withMetricsContext.tsx index e17c3247762..ac6caa0a929 100644 --- a/server/sonar-web/src/main/js/app/components/metrics/withMetricsContext.tsx +++ b/server/sonar-web/src/main/js/app/components/metrics/withMetricsContext.tsx @@ -27,7 +27,9 @@ export interface WithMetricsContextProps { } export default function withMetricsContext

( - WrappedComponent: React.ComponentType

, + WrappedComponent: React.ComponentType< + React.PropsWithChildren> + >, ) { return class WithMetricsContext extends React.PureComponent< Omit diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/qualityProfilesContext.tsx b/server/sonar-web/src/main/js/apps/quality-profiles/qualityProfilesContext.tsx index 3e17c24bc2b..30e6b39962d 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/qualityProfilesContext.tsx +++ b/server/sonar-web/src/main/js/apps/quality-profiles/qualityProfilesContext.tsx @@ -34,17 +34,20 @@ export interface QualityProfilesContextProps { } export function withQualityProfilesContext

>( - WrappedComponent: React.ComponentType

, -): React.ComponentType> { + WrappedComponent: React.ComponentType>>, +): React.ComponentType< + React.PropsWithChildren>> +> { function ComponentWithQualityProfilesProps(props: P) { const context = useOutletContext(); return ; } - (ComponentWithQualityProfilesProps as React.FC

).displayName = getWrappedDisplayName( - WrappedComponent, - 'withQualityProfilesContext', - ); + ( + ComponentWithQualityProfilesProps as React.FC< + React.PropsWithChildren> + > + ).displayName = getWrappedDisplayName(WrappedComponent, 'withQualityProfilesContext'); return ComponentWithQualityProfilesProps; } diff --git a/server/sonar-web/src/main/js/apps/settings/components/inputs/Input.tsx b/server/sonar-web/src/main/js/apps/settings/components/inputs/Input.tsx index 409f60e0324..57001a7be69 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/inputs/Input.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/inputs/Input.tsx @@ -37,7 +37,9 @@ export default function Input(props: DefaultInputProps) { const { definition } = setting; const name = getUniqueName(definition); - let Input: React.ComponentType = PrimitiveInput; + let Input: React.ComponentType< + React.PropsWithChildren> + > = PrimitiveInput; if (isCategoryDefinition(definition) && definition.multiValues) { Input = MultiValueInput; diff --git a/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForSecured.tsx b/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForSecured.tsx index 558e0f93ba5..2a729440828 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForSecured.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForSecured.tsx @@ -35,7 +35,9 @@ interface State { } interface Props extends DefaultInputProps { - input: React.ComponentType; + input: React.ComponentType< + React.PropsWithChildren> + >; } export default class InputForSecured extends React.PureComponent { diff --git a/server/sonar-web/src/main/js/apps/settings/components/inputs/PrimitiveInput.tsx b/server/sonar-web/src/main/js/apps/settings/components/inputs/PrimitiveInput.tsx index b2f09b43cc0..6c23cbafaeb 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/inputs/PrimitiveInput.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/inputs/PrimitiveInput.tsx @@ -29,7 +29,11 @@ import InputForSingleSelectList from './InputForSingleSelectList'; import InputForString from './InputForString'; import InputForText from './InputForText'; -function withOptions(options: string[]): React.ComponentType { +function withOptions( + options: string[], +): React.ComponentType< + React.PropsWithChildren> +> { return function Wrapped(props: DefaultSpecializedInputProps) { return ; }; @@ -39,7 +43,9 @@ export default function PrimitiveInput(props: DefaultSpecializedInputProps) { const { setting, name, isDefault, ...other } = props; const { definition } = setting; const typeMapping: { - [type in SettingType]?: React.ComponentType; + [type in SettingType]?: React.ComponentType< + React.PropsWithChildren> + >; } = { STRING: InputForString, TEXT: InputForText, diff --git a/server/sonar-web/src/main/js/components/a11y/A11yProvider.tsx b/server/sonar-web/src/main/js/components/a11y/A11yProvider.tsx index 131edf13f46..77161816ba5 100644 --- a/server/sonar-web/src/main/js/components/a11y/A11yProvider.tsx +++ b/server/sonar-web/src/main/js/components/a11y/A11yProvider.tsx @@ -26,7 +26,7 @@ interface State { links: A11ySkipLink[]; } -export default class A11yProvider extends React.Component<{}, State> { +export default class A11yProvider extends React.Component { keys: string[] = []; state: State = { links: [] }; diff --git a/server/sonar-web/src/main/js/components/controls/Radio.tsx b/server/sonar-web/src/main/js/components/controls/Radio.tsx index 9c38e35d9cf..8a303c5bad8 100644 --- a/server/sonar-web/src/main/js/components/controls/Radio.tsx +++ b/server/sonar-web/src/main/js/components/controls/Radio.tsx @@ -31,7 +31,7 @@ interface Props { ariaLabel?: string; } -export default class Radio extends React.PureComponent { +export default class Radio extends React.PureComponent> { handleClick = (event: React.MouseEvent) => { event.preventDefault(); diff --git a/server/sonar-web/src/main/js/components/controls/Tooltip.tsx b/server/sonar-web/src/main/js/components/controls/Tooltip.tsx index d84e567c793..cf0171745de 100644 --- a/server/sonar-web/src/main/js/components/controls/Tooltip.tsx +++ b/server/sonar-web/src/main/js/components/controls/Tooltip.tsx @@ -452,7 +452,7 @@ export class TooltipInner extends React.Component { } } -class TooltipPortal extends React.Component { +class TooltipPortal extends React.Component> { el: HTMLElement; constructor(props: {}) { diff --git a/server/sonar-web/src/main/js/components/embed-docs-modal/SuggestionsProvider.tsx b/server/sonar-web/src/main/js/components/embed-docs-modal/SuggestionsProvider.tsx index f5347bd3901..70b972aac12 100644 --- a/server/sonar-web/src/main/js/components/embed-docs-modal/SuggestionsProvider.tsx +++ b/server/sonar-web/src/main/js/components/embed-docs-modal/SuggestionsProvider.tsx @@ -28,7 +28,7 @@ interface State { suggestions: SuggestionLink[]; } -export default class SuggestionsProvider extends React.Component<{}, State> { +export default class SuggestionsProvider extends React.Component { keys: string[] = []; state: State = { suggestions: [] }; diff --git a/server/sonar-web/src/main/js/components/hoc/utils.ts b/server/sonar-web/src/main/js/components/hoc/utils.ts index b36966d78bd..de17d1bdf59 100644 --- a/server/sonar-web/src/main/js/components/hoc/utils.ts +++ b/server/sonar-web/src/main/js/components/hoc/utils.ts @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ export function getWrappedDisplayName

( - WrappedComponent: React.ComponentType

, + WrappedComponent: React.ComponentType>>, hocName: string, ) { const wrappedDisplayName = WrappedComponent.displayName ?? WrappedComponent.name ?? 'Component'; diff --git a/server/sonar-web/src/main/js/components/hoc/whenLoggedIn.tsx b/server/sonar-web/src/main/js/components/hoc/whenLoggedIn.tsx index a86c1c25e19..682f3c22ce1 100644 --- a/server/sonar-web/src/main/js/components/hoc/whenLoggedIn.tsx +++ b/server/sonar-web/src/main/js/components/hoc/whenLoggedIn.tsx @@ -23,7 +23,9 @@ import handleRequiredAuthentication from '../../helpers/handleRequiredAuthentica import { CurrentUser, isLoggedIn } from '../../types/users'; import { getWrappedDisplayName } from './utils'; -export function whenLoggedIn

(WrappedComponent: React.ComponentType

) { +export function whenLoggedIn

( + WrappedComponent: React.ComponentType>>, +) { class Wrapper extends React.Component

{ static displayName = getWrappedDisplayName(WrappedComponent, 'whenLoggedIn'); diff --git a/server/sonar-web/src/main/js/components/hoc/withCLanguageFeature.tsx b/server/sonar-web/src/main/js/components/hoc/withCLanguageFeature.tsx index df6fa13659c..a7eb2b41b75 100644 --- a/server/sonar-web/src/main/js/components/hoc/withCLanguageFeature.tsx +++ b/server/sonar-web/src/main/js/components/hoc/withCLanguageFeature.tsx @@ -22,7 +22,9 @@ import { LanguagesContext } from '../../app/components/languages/LanguagesContex import { getWrappedDisplayName } from './utils'; export function withCLanguageFeature

( - WrappedComponent: React.ComponentType

, + WrappedComponent: React.ComponentType< + React.PropsWithChildren> + >, ) { class Wrapper extends React.Component> { static displayName = getWrappedDisplayName(WrappedComponent, 'withCLanguageFeature'); diff --git a/server/sonar-web/src/main/js/components/hoc/withIndexationContext.tsx b/server/sonar-web/src/main/js/components/hoc/withIndexationContext.tsx index 9d9625c65ec..a6e50ed6e0f 100644 --- a/server/sonar-web/src/main/js/components/hoc/withIndexationContext.tsx +++ b/server/sonar-web/src/main/js/components/hoc/withIndexationContext.tsx @@ -27,7 +27,9 @@ export interface WithIndexationContextProps { } export default function withIndexationContext

( - WrappedComponent: React.ComponentType

, + WrappedComponent: React.ComponentType< + React.PropsWithChildren> + >, ) { return class WithIndexationContext extends React.PureComponent< Omit diff --git a/server/sonar-web/src/main/js/components/hoc/withIndexationGuard.tsx b/server/sonar-web/src/main/js/components/hoc/withIndexationGuard.tsx index f3b882132d4..66efb6f5441 100644 --- a/server/sonar-web/src/main/js/components/hoc/withIndexationGuard.tsx +++ b/server/sonar-web/src/main/js/components/hoc/withIndexationGuard.tsx @@ -25,7 +25,7 @@ export default function withIndexationGuard

({ Component, showIndexationMessage, }: { - Component: React.ComponentType

; + Component: React.ComponentType>>; showIndexationMessage: (props: P) => boolean; }) { return function WithIndexationGuard(props: React.PropsWithChildren

) { diff --git a/server/sonar-web/src/main/js/components/hoc/withKeyboardNavigation.tsx b/server/sonar-web/src/main/js/components/hoc/withKeyboardNavigation.tsx index 0a1e1f0a331..ccf20bab442 100644 --- a/server/sonar-web/src/main/js/components/hoc/withKeyboardNavigation.tsx +++ b/server/sonar-web/src/main/js/components/hoc/withKeyboardNavigation.tsx @@ -36,7 +36,9 @@ export interface WithKeyboardNavigationProps { } export default function withKeyboardNavigation

( - WrappedComponent: React.ComponentType

>, + WrappedComponent: React.ComponentType< + React.PropsWithChildren>> + >, ) { return class Wrapper extends React.Component

{ static displayName = getWrappedDisplayName(WrappedComponent, 'withKeyboardNavigation'); diff --git a/server/sonar-web/src/main/js/components/hoc/withLocation.tsx b/server/sonar-web/src/main/js/components/hoc/withLocation.tsx index ea155eca671..21713420d52 100644 --- a/server/sonar-web/src/main/js/components/hoc/withLocation.tsx +++ b/server/sonar-web/src/main/js/components/hoc/withLocation.tsx @@ -21,7 +21,9 @@ import * as React from 'react'; import { Location, useLocation } from 'react-router-dom'; export default function withLocation

( - WrappedComponent: React.ComponentType

, + WrappedComponent: React.ComponentType< + React.PropsWithChildren> + >, ) { return function WithLocation(props: Omit) { const location = useLocation(); diff --git a/server/sonar-web/src/main/js/components/hoc/withNotifications.tsx b/server/sonar-web/src/main/js/components/hoc/withNotifications.tsx index 310a2ab2c85..236a9b7a91b 100644 --- a/server/sonar-web/src/main/js/components/hoc/withNotifications.tsx +++ b/server/sonar-web/src/main/js/components/hoc/withNotifications.tsx @@ -46,7 +46,9 @@ export interface WithNotificationsProps { } export function withNotifications

( - WrappedComponent: React.ComponentType

, + WrappedComponent: React.ComponentType< + React.PropsWithChildren> + >, ) { class Wrapper extends React.Component { mounted = false; diff --git a/server/sonar-web/src/main/js/components/hoc/withRouter.tsx b/server/sonar-web/src/main/js/components/hoc/withRouter.tsx index 329c601e0ec..b352d94c268 100644 --- a/server/sonar-web/src/main/js/components/hoc/withRouter.tsx +++ b/server/sonar-web/src/main/js/components/hoc/withRouter.tsx @@ -45,8 +45,10 @@ export interface WithRouterProps { } export function withRouter

>( - WrappedComponent: React.ComponentType

, -): React.ComponentType> { + WrappedComponent: React.ComponentType>>, +): React.ComponentType< + React.PropsWithChildren>> +> { function ComponentWithRouterProp(props: P) { const router = useRouter(); const params = useParams(); @@ -55,10 +57,9 @@ export function withRouter

>( return ; } - (ComponentWithRouterProp as React.FC

).displayName = getWrappedDisplayName( - WrappedComponent, - 'withRouter', - ); + ( + ComponentWithRouterProp as React.FC>> + ).displayName = getWrappedDisplayName(WrappedComponent, 'withRouter'); return ComponentWithRouterProp; } diff --git a/server/sonar-web/src/main/js/components/hoc/withScrollTo.tsx b/server/sonar-web/src/main/js/components/hoc/withScrollTo.tsx index 582ab095123..9f410cdc782 100644 --- a/server/sonar-web/src/main/js/components/hoc/withScrollTo.tsx +++ b/server/sonar-web/src/main/js/components/hoc/withScrollTo.tsx @@ -28,8 +28,12 @@ export interface WithScrollToProps { const TOP_OFFSET = 200; const BOTTOM_OFFSET = 10; -export function withScrollTo

(WrappedComponent: React.ComponentClass

) { - return class Wrapper extends React.Component

> { +export function withScrollTo

( + WrappedComponent: React.ComponentClass>, +) { + return class Wrapper extends React.Component< + React.PropsWithChildren

& Partial + > { componentRef?: React.Component | null; node?: Element | Text | null; diff --git a/server/sonar-web/src/main/js/components/icons/ProjectLinkIcon.tsx b/server/sonar-web/src/main/js/components/icons/ProjectLinkIcon.tsx index 0290f6d1f42..880f59ecc11 100644 --- a/server/sonar-web/src/main/js/components/icons/ProjectLinkIcon.tsx +++ b/server/sonar-web/src/main/js/components/icons/ProjectLinkIcon.tsx @@ -43,7 +43,9 @@ export default function ProjectLinkIcon({ type, ...iconProps }: IconProps & ProjectLinkIconProps) { - const getIcon = (): FC => { + const getIcon = (): FC< + React.PropsWithChildren> + > => { switch (type) { case 'issue': return miui ? PulseIcon : BugTrackerIcon; diff --git a/server/sonar-web/src/main/js/components/permissions/HoldersList.tsx b/server/sonar-web/src/main/js/components/permissions/HoldersList.tsx index 27b9f619d04..fbf92f79843 100644 --- a/server/sonar-web/src/main/js/components/permissions/HoldersList.tsx +++ b/server/sonar-web/src/main/js/components/permissions/HoldersList.tsx @@ -46,7 +46,10 @@ interface Props { interface State { initialPermissionsCount: Dict; } -export default class HoldersList extends React.PureComponent { +export default class HoldersList extends React.PureComponent< + React.PropsWithChildren, + State +> { state: State = { initialPermissionsCount: {} }; componentDidUpdate(prevProps: Props) { if (this.props.filter !== prevProps.filter || this.props.query !== prevProps.query) { diff --git a/server/sonar-web/src/main/js/components/rules/MoreInfoRuleDescription.tsx b/server/sonar-web/src/main/js/components/rules/MoreInfoRuleDescription.tsx index c27e5551f2c..118a54a1ef8 100644 --- a/server/sonar-web/src/main/js/components/rules/MoreInfoRuleDescription.tsx +++ b/server/sonar-web/src/main/js/components/rules/MoreInfoRuleDescription.tsx @@ -37,7 +37,9 @@ interface Props { sections?: RuleDescriptionSection[]; } -const EDUCATION_PRINCIPLES_MAP: Dict = { +const EDUCATION_PRINCIPLES_MAP: Dict< + React.ComponentType>> +> = { defense_in_depth: DefenseInDepth, never_trust_user_input: NeverTrustUserInput, }; diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsStep.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsStep.tsx index 12394ea8705..162d2a742e7 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsStep.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsStep.tsx @@ -37,7 +37,9 @@ const BUILD_TOOLS_WITH_NO_ADDITIONAL_OPTIONS = [ ]; const BUILDTOOL_COMPONENT_MAP: { - [x in BuildTools]: React.ComponentType; + [x in BuildTools]: React.ComponentType< + React.PropsWithChildren> + >; } = { [BuildTools.Maven]: Maven, [BuildTools.Gradle]: Gradle, diff --git a/server/sonar-web/src/main/js/components/ui/popups.tsx b/server/sonar-web/src/main/js/components/ui/popups.tsx index b32dc36f650..2daebd0f397 100644 --- a/server/sonar-web/src/main/js/components/ui/popups.tsx +++ b/server/sonar-web/src/main/js/components/ui/popups.tsx @@ -273,7 +273,7 @@ export class PortalPopup extends React.Component { } } -class PortalWrapper extends React.Component { +class PortalWrapper extends React.Component { el: HTMLElement; constructor(props: {}) { diff --git a/server/sonar-web/src/main/js/components/workspace/Workspace.tsx b/server/sonar-web/src/main/js/components/workspace/Workspace.tsx index 9cd80b75943..23f7d388e14 100644 --- a/server/sonar-web/src/main/js/components/workspace/Workspace.tsx +++ b/server/sonar-web/src/main/js/components/workspace/Workspace.tsx @@ -46,7 +46,7 @@ export enum WorkspaceTypes { Component = 'component', } -export default class Workspace extends React.PureComponent<{}, State> { +export default class Workspace extends React.PureComponent { mounted = false; constructor(props: {}) { diff --git a/server/sonar-web/src/main/js/components/workspace/WorkspaceHeader.tsx b/server/sonar-web/src/main/js/components/workspace/WorkspaceHeader.tsx index 52728e4f639..2d5d7af9978 100644 --- a/server/sonar-web/src/main/js/components/workspace/WorkspaceHeader.tsx +++ b/server/sonar-web/src/main/js/components/workspace/WorkspaceHeader.tsx @@ -84,7 +84,7 @@ export default class WorkspaceHeader extends React.PureComponent { } interface WorkspaceHeaderButtonProps { - icon: React.SFC; + icon: React.FC>>; onClick: () => void; tooltip: string; } diff --git a/server/sonar-web/src/main/js/components/workspace/WorkspacePortal.tsx b/server/sonar-web/src/main/js/components/workspace/WorkspacePortal.tsx index 5c037f24087..c0dc45a1ac8 100644 --- a/server/sonar-web/src/main/js/components/workspace/WorkspacePortal.tsx +++ b/server/sonar-web/src/main/js/components/workspace/WorkspacePortal.tsx @@ -20,7 +20,7 @@ import * as React from 'react'; import { createPortal } from 'react-dom'; -export default class WorkspacePortal extends React.PureComponent { +export default class WorkspacePortal extends React.PureComponent { el: HTMLElement; constructor(props: {}) { diff --git a/server/sonar-web/src/main/js/helpers/testUtils.ts b/server/sonar-web/src/main/js/helpers/testUtils.ts index 8f8cc26489f..d4b9704c79a 100644 --- a/server/sonar-web/src/main/js/helpers/testUtils.ts +++ b/server/sonar-web/src/main/js/helpers/testUtils.ts @@ -19,8 +19,15 @@ */ import { ComponentClass, FunctionComponent } from 'react'; -export type ComponentPropsType> = - T extends ComponentClass ? P : T extends FunctionComponent ? P : never; +export type ComponentPropsType< + T extends + | ComponentClass + | FunctionComponent>>, +> = T extends ComponentClass + ? P + : T extends FunctionComponent>> + ? P + : never; export function mockIntersectionObserver(): Function { let callback: Function; diff --git a/server/sonar-web/src/main/js/queries/branch.tsx b/server/sonar-web/src/main/js/queries/branch.tsx index 78bba188984..ffbdff3369f 100644 --- a/server/sonar-web/src/main/js/queries/branch.tsx +++ b/server/sonar-web/src/main/js/queries/branch.tsx @@ -328,9 +328,15 @@ export function useRefreshBranches() { export function withBranchLikes

( WrappedComponent: React.ComponentType< - P & { branchLikes?: BranchLike[]; branchLike?: BranchLike; isFetchingBranch?: boolean } + React.PropsWithChildren< + React.PropsWithChildren< + P & { branchLikes?: BranchLike[]; branchLike?: BranchLike; isFetchingBranch?: boolean } + > + > >, -): React.ComponentType> { +): React.ComponentType< + React.PropsWithChildren>> +> { return function WithBranchLike(p: P) { const { data, isFetching } = useBranchesQuery(p.component); return ( @@ -346,7 +352,11 @@ export function withBranchLikes

( export function withBranchStatusRefresh< P extends { refreshBranchStatus: ReturnType }, ->(WrappedComponent: React.ComponentType

): React.ComponentType> { +>( + WrappedComponent: React.ComponentType>>, +): React.ComponentType< + React.PropsWithChildren>> +> { return function WithBranchStatusRefresh(props: P) { const refresh = useRefreshBranchStatus(); diff --git a/server/sonar-web/src/main/js/types/misc.ts b/server/sonar-web/src/main/js/types/misc.ts index ea95b30ffc6..84faf6ffa49 100644 --- a/server/sonar-web/src/main/js/types/misc.ts +++ b/server/sonar-web/src/main/js/types/misc.ts @@ -18,4 +18,5 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -export type FCProps> = Parameters[0]; +export type FCProps>> = + Parameters[0]; -- 2.39.5