diff --git a/.eslintrc.js b/.eslintrc.js index 75a74ed371c4..83e9479ce0c4 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -116,7 +116,7 @@ module.exports = { }, { selector: ['parameter', 'method'], - format: ['camelCase'], + format: ['camelCase', 'PascalCase'], }, ], '@typescript-eslint/ban-types': [ diff --git a/src/components/withEnvironment.js b/src/components/withEnvironment.tsx similarity index 50% rename from src/components/withEnvironment.js rename to src/components/withEnvironment.tsx index 3aa9b86e82c8..0f065eac68fe 100644 --- a/src/components/withEnvironment.js +++ b/src/components/withEnvironment.tsx @@ -1,21 +1,28 @@ -import React, {createContext, useState, useEffect, forwardRef, useContext, useMemo} from 'react'; -import PropTypes from 'prop-types'; +import React, {ComponentType, RefAttributes, ReactNode, ForwardedRef, ReactElement, createContext, useState, useEffect, forwardRef, useContext, useMemo} from 'react'; +import {ValueOf} from 'type-fest'; import * as Environment from '../libs/Environment/Environment'; import CONST from '../CONST'; import getComponentDisplayName from '../libs/getComponentDisplayName'; -const EnvironmentContext = createContext(null); +type EnvironmentProviderProps = { + /** Actual content wrapped by this component */ + children: ReactNode; +}; + +type EnvironmentValue = ValueOf; -const environmentPropTypes = { +type EnvironmentContextValue = { /** The string value representing the current environment */ - environment: PropTypes.string.isRequired, + environment: EnvironmentValue; /** The string value representing the URL of the current environment */ - environmentURL: PropTypes.string.isRequired, + environmentURL: string; }; -function EnvironmentProvider({children}) { - const [environment, setEnvironment] = useState(CONST.ENVIRONMENT.PRODUCTION); +const EnvironmentContext = createContext(null); + +function EnvironmentProvider({children}: EnvironmentProviderProps): ReactElement { + const [environment, setEnvironment] = useState(CONST.ENVIRONMENT.PRODUCTION); const [environmentURL, setEnvironmentURL] = useState(CONST.NEW_EXPENSIFY_URL); useEffect(() => { @@ -24,7 +31,7 @@ function EnvironmentProvider({children}) { }, []); const contextValue = useMemo( - () => ({ + (): EnvironmentContextValue => ({ environment, environmentURL, }), @@ -35,28 +42,27 @@ function EnvironmentProvider({children}) { } EnvironmentProvider.displayName = 'EnvironmentProvider'; -EnvironmentProvider.propTypes = { - /** Actual content wrapped by this component */ - children: PropTypes.node.isRequired, -}; -export default function withEnvironment(WrappedComponent) { - const WithEnvironment = forwardRef((props, ref) => { - const {environment, environmentURL} = useContext(EnvironmentContext); +export default function withEnvironment( + WrappedComponent: ComponentType>, +): (props: Omit & React.RefAttributes) => ReactElement | null { + function WithEnvironment(props: Omit, ref: ForwardedRef): ReactElement { + const {environment, environmentURL} = useContext(EnvironmentContext) ?? {}; return ( ); - }); + } WithEnvironment.displayName = `withEnvironment(${getComponentDisplayName(WrappedComponent)})`; - return WithEnvironment; + return forwardRef(WithEnvironment); } -export {EnvironmentContext, environmentPropTypes, EnvironmentProvider}; +export {EnvironmentContext, EnvironmentProvider}; +export type {EnvironmentContextValue}; diff --git a/src/hooks/useEnvironment.js b/src/hooks/useEnvironment.ts similarity index 59% rename from src/hooks/useEnvironment.js rename to src/hooks/useEnvironment.ts index e29e60a563b2..0b1601ee972a 100644 --- a/src/hooks/useEnvironment.js +++ b/src/hooks/useEnvironment.ts @@ -1,9 +1,15 @@ import {useContext} from 'react'; import CONST from '../CONST'; import {EnvironmentContext} from '../components/withEnvironment'; +import type {EnvironmentContextValue} from '../components/withEnvironment'; -export default function useEnvironment() { - const {environment, environmentURL} = useContext(EnvironmentContext); +type UseEnvironment = Partial & { + isProduction: boolean; + isDevelopment: boolean; +}; + +export default function useEnvironment(): UseEnvironment { + const {environment, environmentURL} = useContext(EnvironmentContext) ?? {}; return { environment, environmentURL, diff --git a/src/libs/getComponentDisplayName.ts b/src/libs/getComponentDisplayName.ts index fd1bbcaea521..0bf52d543a84 100644 --- a/src/libs/getComponentDisplayName.ts +++ b/src/libs/getComponentDisplayName.ts @@ -1,6 +1,6 @@ import {ComponentType} from 'react'; /** Returns the display name of a component */ -export default function getComponentDisplayName(component: ComponentType): string { +export default function getComponentDisplayName(component: ComponentType): string { return component.displayName ?? component.name ?? 'Component'; } diff --git a/src/pages/ShareCodePage.js b/src/pages/ShareCodePage.js index e6d36ebc7070..f0f0ef7d09fd 100644 --- a/src/pages/ShareCodePage.js +++ b/src/pages/ShareCodePage.js @@ -1,6 +1,7 @@ import React from 'react'; import {View, ScrollView} from 'react-native'; import _ from 'underscore'; +import PropTypes from 'prop-types'; import ScreenWrapper from '../components/ScreenWrapper'; import HeaderWithBackButton from '../components/HeaderWithBackButton'; import Navigation from '../libs/Navigation/Navigation'; @@ -20,16 +21,18 @@ import CONST from '../CONST'; import ContextMenuItem from '../components/ContextMenuItem'; import * as UserUtils from '../libs/UserUtils'; import ROUTES from '../ROUTES'; -import withEnvironment, {environmentPropTypes} from '../components/withEnvironment'; +import withEnvironment from '../components/withEnvironment'; import * as Url from '../libs/Url'; const propTypes = { /** The report currently being looked at */ report: reportPropTypes, + /** The string value representing the URL of the current environment */ + environmentURL: PropTypes.string.isRequired, + ...withLocalizePropTypes, ...withCurrentUserPersonalDetailsPropTypes, - ...environmentPropTypes, }; const defaultProps = {