Skip to content

Commit

Permalink
Merge pull request #43557 from software-mansion-labs/ts/enable-no-uns…
Browse files Browse the repository at this point in the history
…afe-member-access

Enable `no-unsafe-member-access` eslint rule
  • Loading branch information
mountiny authored Jun 25, 2024
2 parents 621e8fc + 0bb01b7 commit cb40377
Show file tree
Hide file tree
Showing 71 changed files with 518 additions and 389 deletions.
1 change: 0 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ module.exports = {
},
rules: {
// TypeScript specific rules
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/prefer-enum-initializers': 'error',
'@typescript-eslint/no-var-requires': 'off',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as github from '@actions/github';
import type {WebhookPayload} from '@actions/github/lib/interfaces';
import {parse} from '@babel/parser';
import traverse from '@babel/traverse';
import CONST from '@github/libs/CONST';
Expand All @@ -8,6 +9,15 @@ import type Category from './Category';

type SuperClassType = {superClass: {name?: string; object: {name: string}; property: {name: string}} | null; name: string};

type GithubPaylod = WebhookPayload & {
// eslint-disable-next-line @typescript-eslint/naming-convention
pull_request?: {
head: {
ref?: string;
};
};
};

const items = [
"I verified that similar component doesn't exist in the codebase",
'I verified that all props are defined accurately and each prop has a `/** comment above it */`',
Expand Down Expand Up @@ -77,7 +87,7 @@ async function detectReactComponentInFile(filename: string): Promise<boolean | u
owner: CONST.GITHUB_OWNER,
repo: CONST.APP_REPO,
path: filename,
ref: github.context.payload.pull_request?.head.ref,
ref: (github.context.payload as GithubPaylod)?.pull_request?.head.ref,
};
try {
const {data} = await GithubUtils.octokit.repos.getContent(params);
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/javascript/authorChecklist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16967,7 +16967,7 @@ async function detectReactComponentInFile(filename) {
owner: CONST_1.default.GITHUB_OWNER,
repo: CONST_1.default.APP_REPO,
path: filename,
ref: github.context.payload.pull_request?.head.ref,
ref: github.context.payload?.pull_request?.head.ref,
};
try {
const { data } = await GithubUtils_1.default.octokit.repos.getContent(params);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ import GitUtils from '@github/libs/GitUtils';

type IssuesCreateResponse = Awaited<ReturnType<typeof GithubUtils.octokit.issues.create>>['data'];

type PackageJSON = {
version: string;
};

async function run(): Promise<IssuesCreateResponse | void> {
// Note: require('package.json').version does not work because ncc will resolve that to a plain string at compile time
const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
const newVersionTag: string = packageJson.version;
const packageJson: PackageJSON = JSON.parse(fs.readFileSync('package.json', 'utf8'));
const newVersionTag = packageJson.version;

try {
// Start by fetching the list of recent StagingDeployCash issues, along with the list of open deploy blockers
Expand Down
6 changes: 5 additions & 1 deletion .storybook/webpack.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ type CustomWebpackConfig = {

type CustomWebpackFunction = ({file, platform}: Environment) => CustomWebpackConfig;

type WebpackModule = {
default: CustomWebpackFunction;
};

let envFile: string;
switch (process.env.ENV) {
case 'production':
Expand All @@ -34,7 +38,7 @@ switch (process.env.ENV) {
}

const env = dotenv.config({path: path.resolve(__dirname, `../${envFile}`)});
const customFunction: CustomWebpackFunction = require('../config/webpack/webpack.common').default;
const customFunction = require<WebpackModule>('../config/webpack/webpack.common').default;

const custom: CustomWebpackConfig = customFunction({file: envFile});

Expand Down
6 changes: 3 additions & 3 deletions __mocks__/react-native-webview.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type {View as RNView} from 'react-native';
import type ReactNative from 'react-native';

jest.mock('react-native-webview', () => {
const {View} = require('react-native');
const {View} = require<typeof ReactNative>('react-native');
return {
WebView: () => View as RNView,
WebView: () => View,
};
});
6 changes: 5 additions & 1 deletion desktop/createDownloadQueue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ type CreateDownloadQueue = () => {
dequeueDownloadItem: () => DownloadItem | undefined;
};

type CreateDownloadQueueModule = {
default: CreateDownloadQueue;
};

/**
* Returns the filename with extension based on the given name and MIME type.
* @param name - The name of the file.
Expand Down Expand Up @@ -119,4 +123,4 @@ const createDownloadQueue: CreateDownloadQueue = () => {
};

export default createDownloadQueue;
export type {DownloadItem, CreateDownloadQueue};
export type {DownloadItem, CreateDownloadQueueModule};
4 changes: 2 additions & 2 deletions desktop/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ import CONST from '@src/CONST';
import type {TranslationPaths} from '@src/languages/types';
import type PlatformSpecificUpdater from '@src/setup/platformSetup/types';
import type {Locale} from '@src/types/onyx';
import type {CreateDownloadQueue, DownloadItem} from './createDownloadQueue';
import type {CreateDownloadQueueModule, DownloadItem} from './createDownloadQueue';
import ELECTRON_EVENTS from './ELECTRON_EVENTS';

const createDownloadQueue: CreateDownloadQueue = require('./createDownloadQueue').default;
const createDownloadQueue = require<CreateDownloadQueueModule>('./createDownloadQueue').default;

const port = process.env.PORT ?? 8082;
const {DESKTOP_SHORTCUT_ACCELERATOR, LOCALES} = CONST;
Expand Down
2 changes: 1 addition & 1 deletion src/components/AttachmentModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ function AttachmentModal({
}, []);

const isDirectoryCheck = useCallback((data: FileObject) => {
if ('webkitGetAsEntry' in data && typeof data.webkitGetAsEntry === 'function' && data.webkitGetAsEntry().isDirectory) {
if ('webkitGetAsEntry' in data && (data as DataTransferItem).webkitGetAsEntry()?.isDirectory) {
setIsAttachmentInvalid(true);
setAttachmentInvalidReasonTitle('attachmentPicker.attachmentError');
setAttachmentInvalidReason('attachmentPicker.folderNotAllowedMessage');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const launchCamera: LaunchCamera = (options, callback) => {

launchCameraImagePicker(options, callback);
})
.catch((error) => {
.catch((error: ErrorLaunchCamera) => {
/* Intercept the permission error as well as any other errors and call the callback
* follow the same pattern expected for image picker results */
callback({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const launchCamera: LaunchCamera = (options, callback) => {

launchCameraImagePicker(options, callback);
})
.catch((error) => {
.catch((error: ErrorLaunchCamera) => {
/* Intercept the permission error as well as any other errors and call the callback
* follow the same pattern expected for image picker results */
callback({
Expand Down
25 changes: 12 additions & 13 deletions src/components/Hoverable/ActiveHoverable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import type HoverableProps from './types';

type ActiveHoverableProps = Omit<HoverableProps, 'disabled'>;

type OnMouseEvent = (e: MouseEvent) => void;
type MouseEvents = 'onMouseEnter' | 'onMouseLeave' | 'onMouseMove' | 'onBlur';

type OnMouseEvents = Record<MouseEvents, (e: MouseEvent) => void>;

function ActiveHoverable({onHoverIn, onHoverOut, shouldHandleScroll, shouldFreezeCapture, children}: ActiveHoverableProps, outerRef: Ref<HTMLElement>) {
const [isHovered, setIsHovered] = useState(false);
Expand Down Expand Up @@ -100,26 +102,23 @@ function ActiveHoverable({onHoverIn, onHoverOut, shouldHandleScroll, shouldFreez

const child = useMemo(() => getReturnValue(children, !isScrollingRef.current && isHovered), [children, isHovered]);

const childOnMouseEnter: OnMouseEvent = child.props.onMouseEnter;
const childOnMouseLeave: OnMouseEvent = child.props.onMouseLeave;
const childOnMouseMove: OnMouseEvent = child.props.onMouseMove;
const childOnBlur: OnMouseEvent = child.props.onBlur;
const {onMouseEnter, onMouseLeave, onMouseMove, onBlur}: OnMouseEvents = child.props;

const hoverAndForwardOnMouseEnter = useCallback(
(e: MouseEvent) => {
isVisibiltyHidden.current = false;
updateIsHovered(true);
childOnMouseEnter?.(e);
onMouseEnter?.(e);
},
[updateIsHovered, childOnMouseEnter],
[updateIsHovered, onMouseEnter],
);

const unhoverAndForwardOnMouseLeave = useCallback(
(e: MouseEvent) => {
updateIsHovered(false);
childOnMouseLeave?.(e);
onMouseLeave?.(e);
},
[updateIsHovered, childOnMouseLeave],
[updateIsHovered, onMouseLeave],
);

const unhoverAndForwardOnBlur = useCallback(
Expand All @@ -130,18 +129,18 @@ function ActiveHoverable({onHoverIn, onHoverOut, shouldHandleScroll, shouldFreez
setIsHovered(false);
}

childOnBlur?.(event);
onBlur?.(event);
},
[childOnBlur],
[onBlur],
);

const handleAndForwardOnMouseMove = useCallback(
(e: MouseEvent) => {
isVisibiltyHidden.current = false;
updateIsHovered(true);
childOnMouseMove?.(e);
onMouseMove?.(e);
},
[updateIsHovered, childOnMouseMove],
[updateIsHovered, onMouseMove],
);

return cloneElement(child, {
Expand Down
3 changes: 2 additions & 1 deletion src/components/Modal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import StatusBar from '@libs/StatusBar';
import CONST from '@src/CONST';
import BaseModal from './BaseModal';
import type BaseModalProps from './types';
import type {WindowState} from './types';

function Modal({fullscreen = true, onModalHide = () => {}, type, onModalShow = () => {}, children, shouldHandleNavigationBack, ...rest}: BaseModalProps) {
const theme = useTheme();
Expand All @@ -22,7 +23,7 @@ function Modal({fullscreen = true, onModalHide = () => {}, type, onModalShow = (
const hideModal = () => {
setStatusBarColor(previousStatusBarColor);
onModalHide();
if (window.history.state?.shouldGoBack) {
if ((window.history.state as WindowState)?.shouldGoBack) {
window.history.back();
}
};
Expand Down
6 changes: 5 additions & 1 deletion src/components/Modal/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ type PopoverAnchorPosition = {
left?: number;
};

type WindowState = {
shouldGoBack: boolean;
};

type BaseModalProps = Partial<ModalProps> & {
/** Decides whether the modal should cover fullscreen. FullScreen modal has backdrop */
fullscreen?: boolean;
Expand Down Expand Up @@ -86,4 +90,4 @@ type BaseModalProps = Partial<ModalProps> & {
};

export default BaseModalProps;
export type {PopoverAnchorPosition};
export type {PopoverAnchorPosition, WindowState};
5 changes: 2 additions & 3 deletions src/components/Onfido/BaseOnfidoWeb.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {Onfido as OnfidoSDK} from 'onfido-sdk-ui';
import type {ErrorType} from 'onfido-sdk-ui/types/Types';
import React, {forwardRef, useEffect} from 'react';
import type {ForwardedRef} from 'react';
import type {LocaleContextProps} from '@components/LocaleContextProvider';
Expand All @@ -12,7 +11,7 @@ import variables from '@styles/variables';
import CONST from '@src/CONST';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import './index.css';
import type {OnfidoElement, OnfidoProps} from './types';
import type {OnfidoElement, OnfidoError, OnfidoProps} from './types';

type InitializeOnfidoProps = OnfidoProps &
Pick<LocaleContextProps, 'translate' | 'preferredLocale'> & {
Expand Down Expand Up @@ -93,7 +92,7 @@ function initializeOnfido({sdkToken, onSuccess, onError, onUserExit, preferredLo
}
onSuccess(data);
},
onError: (error: ErrorType) => {
onError: (error: OnfidoError) => {
const errorType = error.type;
const errorMessage: string = error.message ?? CONST.ERROR.UNKNOWN_ERROR;
Log.hmmm('Onfido error', {errorType, errorMessage});
Expand Down
5 changes: 2 additions & 3 deletions src/components/Onfido/index.native.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {OnfidoCaptureType, OnfidoCountryCode, OnfidoDocumentType, Onfido as OnfidoSDK, OnfidoTheme} from '@onfido/react-native-sdk';
import type {ErrorType} from 'onfido-sdk-ui/types/Types';
import React, {useEffect} from 'react';
import {Alert, Linking} from 'react-native';
import {checkMultiple, PERMISSIONS, RESULTS} from 'react-native-permissions';
Expand All @@ -9,7 +8,7 @@ import getPlatform from '@libs/getPlatform';
import Log from '@libs/Log';
import CONST from '@src/CONST';
import type {TranslationPaths} from '@src/languages/types';
import type {OnfidoProps} from './types';
import type {OnfidoError, OnfidoProps} from './types';

function Onfido({sdkToken, onUserExit, onSuccess, onError}: OnfidoProps) {
const {translate} = useLocalize();
Expand All @@ -30,7 +29,7 @@ function Onfido({sdkToken, onUserExit, onSuccess, onError}: OnfidoProps) {
},
})
.then(onSuccess)
.catch((error: ErrorType) => {
.catch((error: OnfidoError) => {
const errorMessage: string = error.message ?? CONST.ERROR.UNKNOWN_ERROR;
const errorType = error.type;

Expand Down
6 changes: 5 additions & 1 deletion src/components/Onfido/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,8 @@ type OnfidoProps = {
onError: (error?: string) => void;
};

export type {OnfidoProps, OnfidoElement, OnfidoData, OnfidoDataWithApplicantID};
type OnfidoError = Error & {
type?: string;
};

export type {OnfidoProps, OnfidoElement, OnfidoData, OnfidoDataWithApplicantID, OnfidoError};
8 changes: 5 additions & 3 deletions src/components/SignInButtons/GoogleSignIn/index.native.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as Session from '@userActions/Session';
import CONFIG from '@src/CONFIG';
import CONST from '@src/CONST';
import type {GoogleSignInProps} from '.';
import type GoogleError from './types';

/**
* Google Sign In method for iOS and android that returns identityToken.
Expand All @@ -25,10 +26,11 @@ function googleSignInRequest() {
GoogleSignin.signIn()
.then((response) => response.idToken)
.then((token) => Session.beginGoogleSignIn(token))
.catch((error) => {
.catch((error: GoogleError | undefined) => {
// Handle unexpected error shape
if (error === undefined || error.code === undefined) {
Log.alert(`[Google Sign In] Google sign in failed: ${error}`);
if (error?.code === undefined) {
Log.alert(`[Google Sign In] Google sign in failed: ${JSON.stringify(error)}`);
return;
}
/** The logged code is useful for debugging any new errors that are not specifically handled. To decode, see:
- The common status codes documentation: https://developers.google.com/android/reference/com/google/android/gms/common/api/CommonStatusCodes
Expand Down
5 changes: 5 additions & 0 deletions src/components/SignInButtons/GoogleSignIn/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type GoogleError = Error & {
code?: string;
};

export default GoogleError;
6 changes: 5 additions & 1 deletion src/components/Tooltip/BaseTooltip/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import GenericTooltip from '@components/Tooltip/GenericTooltip';
import type TooltipProps from '@components/Tooltip/types';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';

type MouseEvents = {
onMouseEnter: (e: MouseEvent) => void | undefined;
};

const hasHoverSupport = DeviceCapabilities.hasHoverSupport();

/**
Expand Down Expand Up @@ -76,7 +80,7 @@ function Tooltip({children, shouldHandleScroll = false, ...props}: TooltipProps,
(e: MouseEvent) => {
updateTargetAndMousePosition(e);
if (React.isValidElement(children)) {
const onMouseEnter: (e: MouseEvent) => void | undefined = children.props.onMouseEnter;
const onMouseEnter = (children.props as MouseEvents).onMouseEnter;
onMouseEnter?.(e);
}
},
Expand Down
6 changes: 2 additions & 4 deletions src/libs/DomUtils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ const addCSS = (css: string, styleId: string) => {
if (existingStyle) {
if ('styleSheet' in existingStyle) {
// Supports IE8 and below
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(existingStyle.styleSheet as any).cssText = css;
(existingStyle.styleSheet as CSSStyleDeclaration).cssText = css;
} else {
existingStyle.innerHTML = css;
}
Expand All @@ -20,8 +19,7 @@ const addCSS = (css: string, styleId: string) => {

if ('styleSheet' in styleElement) {
// Supports IE8 and below
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(styleElement.styleSheet as any).cssText = css;
(styleElement.styleSheet as CSSStyleDeclaration).cssText = css;
} else {
styleElement.appendChild(document.createTextNode(css));
}
Expand Down
Loading

0 comments on commit cb40377

Please sign in to comment.