Skip to content

Commit

Permalink
Merge pull request #44003 from software-mansion-labs/ts/no-unsafe-ass…
Browse files Browse the repository at this point in the history
…ignment

[No QA] Enable `no-unsafe-assignment` eslint rule
  • Loading branch information
mountiny authored Jul 4, 2024
2 parents 21f74e9 + 0cc3676 commit b49d5b8
Show file tree
Hide file tree
Showing 67 changed files with 176 additions and 190 deletions.
1 change: 0 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ module.exports = {
},
rules: {
// TypeScript specific rules
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/prefer-enum-initializers': 'error',
'@typescript-eslint/no-var-requires': 'off',
'@typescript-eslint/no-non-null-assertion': 'error',
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/javascript/bumpVersion/bumpVersion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ if (!semanticVersionLevel || !versionUpdater.isValidSemverLevel(semanticVersionL
console.log(`Invalid input for 'SEMVER_LEVEL': ${semanticVersionLevel}`, `Defaulting to: ${semanticVersionLevel}`);
}

const {version: previousVersion}: PackageJson = JSON.parse(fs.readFileSync('./package.json').toString());
const {version: previousVersion} = JSON.parse(fs.readFileSync('./package.json').toString()) as PackageJson;
if (!previousVersion) {
core.setFailed('Error: Could not read package.json');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import GitUtils from '@github/libs/GitUtils';

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

type PackageJSON = {
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: PackageJSON = JSON.parse(fs.readFileSync('package.json', 'utf8'));
const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8')) as PackageJson;
const newVersionTag = packageJson.version;

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const run = () => {
}

try {
const current: RegressionEntry = JSON.parse(entry);
const current = JSON.parse(entry) as RegressionEntry;

// Extract timestamp, Graphite accepts timestamp in seconds
if (current.metadata?.creationDate) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ function run() {
core.setFailed(`'Error: Invalid input for 'SEMVER_LEVEL': ${semverLevel}`);
}

const {version: currentVersion}: PackageJson = JSON.parse(readFileSync('./package.json', 'utf8'));
const {version: currentVersion} = JSON.parse(readFileSync('./package.json', 'utf8')) as PackageJson;
if (!currentVersion) {
core.setFailed('Error: Could not read package.json');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type {CompareResult, PerformanceEntry} from '@callstack/reassure-compare/
import fs from 'fs';

const run = (): boolean => {
const regressionOutput: CompareResult = JSON.parse(fs.readFileSync('.reassure/output.json', 'utf8'));
const regressionOutput = JSON.parse(fs.readFileSync('.reassure/output.json', 'utf8')) as CompareResult;
const countDeviation = Number(core.getInput('COUNT_DEVIATION', {required: true}));
const durationDeviation = Number(core.getInput('DURATION_DEVIATION_PERCENTAGE', {required: true}));

Expand Down
16 changes: 8 additions & 8 deletions __mocks__/@ua/react-native-airship.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,31 @@ const iOS: Partial<typeof AirshipIOS> = {
},
};

const pushIOS: AirshipPushIOS = jest.fn().mockImplementation(() => ({
const pushIOS = jest.fn().mockImplementation(() => ({
setBadgeNumber: jest.fn(),
setForegroundPresentationOptions: jest.fn(),
setForegroundPresentationOptionsCallback: jest.fn(),
}))();
}))() as AirshipPushIOS;

const pushAndroid: AirshipPushAndroid = jest.fn().mockImplementation(() => ({
const pushAndroid = jest.fn().mockImplementation(() => ({
setForegroundDisplayPredicate: jest.fn(),
}))();
}))() as AirshipPushAndroid;

const push: AirshipPush = jest.fn().mockImplementation(() => ({
const push = jest.fn().mockImplementation(() => ({
iOS: pushIOS,
android: pushAndroid,
enableUserNotifications: () => Promise.resolve(false),
clearNotifications: jest.fn(),
getNotificationStatus: () => Promise.resolve({airshipOptIn: false, systemEnabled: false, airshipEnabled: false}),
getActiveNotifications: () => Promise.resolve([]),
}))();
}))() as AirshipPush;

const contact: AirshipContact = jest.fn().mockImplementation(() => ({
const contact = jest.fn().mockImplementation(() => ({
identify: jest.fn(),
getNamedUserId: () => Promise.resolve(undefined),
reset: jest.fn(),
module: jest.fn(),
}))();
}))() as AirshipContact;

const Airship: Partial<AirshipRoot> = {
addListener: jest.fn(),
Expand Down
1 change: 1 addition & 0 deletions __mocks__/fs.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
const {fs} = require('memfs');

module.exports = fs;
4 changes: 2 additions & 2 deletions __mocks__/react-native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jest.doMock('react-native', () => {
};
};

const reactNativeMock: ReactNativeMock = Object.setPrototypeOf(
const reactNativeMock = Object.setPrototypeOf(
{
NativeModules: {
...ReactNative.NativeModules,
Expand Down Expand Up @@ -102,7 +102,7 @@ jest.doMock('react-native', () => {
},
},
ReactNative,
);
) as ReactNativeMock;

return reactNativeMock;
});
13 changes: 5 additions & 8 deletions config/webpack/webpack.common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,24 @@ import dotenv from 'dotenv';
import fs from 'fs';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import path from 'path';
import type {Compiler, Configuration} from 'webpack';
import type {Class} from 'type-fest';
import type {Configuration, WebpackPluginInstance} from 'webpack';
import {DefinePlugin, EnvironmentPlugin, IgnorePlugin, ProvidePlugin} from 'webpack';
import {BundleAnalyzerPlugin} from 'webpack-bundle-analyzer';
import CustomVersionFilePlugin from './CustomVersionFilePlugin';
import type Environment from './types';

// importing anything from @vue/preload-webpack-plugin causes an error
type Options = {
rel: string;
as: string;
fileWhitelist: RegExp[];
include: string;
};

type PreloadWebpackPluginClass = {
new (options?: Options): PreloadWebpackPluginClass;
apply: (compiler: Compiler) => void;
};
type PreloadWebpackPluginClass = Class<WebpackPluginInstance, [Options]>;

// require is necessary, there are no types for this package and the declaration file can't be seen by the build process which causes an error.
const PreloadWebpackPlugin: PreloadWebpackPluginClass = require('@vue/preload-webpack-plugin');
// require is necessary, importing anything from @vue/preload-webpack-plugin causes an error
const PreloadWebpackPlugin = require('@vue/preload-webpack-plugin') as PreloadWebpackPluginClass;

const includeModules = [
'react-native-animatable',
Expand Down
4 changes: 2 additions & 2 deletions desktop/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ const manuallyCheckForUpdates = (menuItem?: MenuItem, browserWindow?: BrowserWin

autoUpdater
.checkForUpdates()
.catch((error) => {
.catch((error: unknown) => {
isSilentUpdating = false;
return {error};
})
Expand Down Expand Up @@ -617,7 +617,7 @@ const mainWindow = (): Promise<void> => {
});

const downloadQueue = createDownloadQueue();
ipcMain.on(ELECTRON_EVENTS.DOWNLOAD, (event, downloadData) => {
ipcMain.on(ELECTRON_EVENTS.DOWNLOAD, (event, downloadData: DownloadItem) => {
const downloadItem: DownloadItem = {
...downloadData,
win: browserWindow,
Expand Down
4 changes: 2 additions & 2 deletions jest/setup.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import '@shopify/flash-list/jestSetup';
import 'react-native-gesture-handler/jestSetup';
import type * as RNKeyboardController from 'react-native-keyboard-controller';
import mockStorage from 'react-native-onyx/dist/storage/__mocks__';
import 'setimmediate';
import mockFSLibrary from './setupMockFullstoryLib';
Expand Down Expand Up @@ -54,5 +55,4 @@ jest.mock('react-native-share', () => ({
default: jest.fn(),
}));

// eslint-disable-next-line @typescript-eslint/no-unsafe-return
jest.mock('react-native-keyboard-controller', () => require('react-native-keyboard-controller/jest'));
jest.mock('react-native-keyboard-controller', () => require<typeof RNKeyboardController>('react-native-keyboard-controller/jest'));
2 changes: 1 addition & 1 deletion jest/setupMockFullstoryLib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default function mockFSLibrary() {
return {
FSPage(): FSPageInterface {
return {
start: jest.fn(),
start: jest.fn(() => {}),
};
},
default: Fullstory,
Expand Down
2 changes: 1 addition & 1 deletion src/components/AttachmentModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ function AttachmentModal({
}
let fileObject = data;
if ('getAsFile' in data && typeof data.getAsFile === 'function') {
fileObject = data.getAsFile();
fileObject = data.getAsFile() as FileObject;
}
if (!fileObject) {
return;
Expand Down
2 changes: 1 addition & 1 deletion src/components/Attachments/AttachmentCarousel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ function AttachmentCarousel({report, reportActions, parentReportActions, source,
return;
}

const item: Attachment = entry.item;
const item = entry.item as Attachment;
if (entry.index !== null) {
setPage(entry.index);
setActiveSource(item.source);
Expand Down
2 changes: 1 addition & 1 deletion src/components/Composer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ function Composer(
}, []);

useEffect(() => {
const scrollingListener = DeviceEventEmitter.addListener(CONST.EVENTS.SCROLLING, (scrolling) => {
const scrollingListener = DeviceEventEmitter.addListener(CONST.EVENTS.SCROLLING, (scrolling: boolean) => {
isReportFlatListScrolling.current = scrolling;
});

Expand Down
1 change: 0 additions & 1 deletion src/components/FlatList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ function MVCPFlatList<TItem>({maintainVisibleContentPosition, horizontal = false
return horizontal ? getScrollableNode(scrollRef.current)?.scrollLeft ?? 0 : getScrollableNode(scrollRef.current)?.scrollTop ?? 0;
}, [horizontal]);

// eslint-disable-next-line @typescript-eslint/no-unsafe-return
const getContentView = useCallback(() => getScrollableNode(scrollRef.current)?.childNodes[0], []);

const scrollToOffset = useCallback(
Expand Down
4 changes: 2 additions & 2 deletions src/components/Hoverable/ActiveHoverable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ function ActiveHoverable({onHoverIn, onHoverOut, shouldHandleScroll, shouldFreez
return;
}

const scrollingListener = DeviceEventEmitter.addListener(CONST.EVENTS.SCROLLING, (scrolling) => {
const scrollingListener = DeviceEventEmitter.addListener(CONST.EVENTS.SCROLLING, (scrolling: boolean) => {
isScrollingRef.current = scrolling;
if (!isScrollingRef.current) {
setIsHovered(isHoveredRef.current);
Expand Down Expand Up @@ -102,7 +102,7 @@ function ActiveHoverable({onHoverIn, onHoverOut, shouldHandleScroll, shouldFreez

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

const {onMouseEnter, onMouseLeave, onMouseMove, onBlur}: OnMouseEvents = child.props;
const {onMouseEnter, onMouseLeave, onMouseMove, onBlur} = child.props as OnMouseEvents;

const hoverAndForwardOnMouseEnter = useCallback(
(e: MouseEvent) => {
Expand Down
2 changes: 1 addition & 1 deletion src/components/IFrame.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ function getNewDotURL(url: string): string {

let params: Record<string, string>;
try {
params = JSON.parse(paramString);
params = JSON.parse(paramString) as Record<string, string>;
} catch {
params = {};
}
Expand Down
29 changes: 15 additions & 14 deletions src/components/LottieAnimations/index.tsx
Original file line number Diff line number Diff line change
@@ -1,80 +1,81 @@
import type {LottieViewProps} from 'lottie-react-native';
import colors from '@styles/theme/colors';
import variables from '@styles/variables';
import type DotLottieAnimation from './types';

const DotLottieAnimations = {
Abracadabra: {
file: require('@assets/animations/Abracadabra.lottie'),
file: require<LottieViewProps['source']>('@assets/animations/Abracadabra.lottie'),
w: 375,
h: 400,
},
FastMoney: {
file: require('@assets/animations/FastMoney.lottie'),
file: require<LottieViewProps['source']>('@assets/animations/FastMoney.lottie'),
w: 375,
h: 240,
},
Fireworks: {
file: require('@assets/animations/Fireworks.lottie'),
file: require<LottieViewProps['source']>('@assets/animations/Fireworks.lottie'),
w: 360,
h: 360,
},
Hands: {
file: require('@assets/animations/Hands.lottie'),
file: require<LottieViewProps['source']>('@assets/animations/Hands.lottie'),
w: 375,
h: 375,
},
PreferencesDJ: {
file: require('@assets/animations/PreferencesDJ.lottie'),
file: require<LottieViewProps['source']>('@assets/animations/PreferencesDJ.lottie'),
w: 375,
h: 240,
backgroundColor: colors.blue500,
},
ReviewingBankInfo: {
file: require('@assets/animations/ReviewingBankInfo.lottie'),
file: require<LottieViewProps['source']>('@assets/animations/ReviewingBankInfo.lottie'),
w: 280,
h: 280,
},
WorkspacePlanet: {
file: require('@assets/animations/WorkspacePlanet.lottie'),
file: require<LottieViewProps['source']>('@assets/animations/WorkspacePlanet.lottie'),
w: 375,
h: 240,
backgroundColor: colors.pink800,
},
SaveTheWorld: {
file: require('@assets/animations/SaveTheWorld.lottie'),
file: require<LottieViewProps['source']>('@assets/animations/SaveTheWorld.lottie'),
w: 375,
h: 240,
},
Safe: {
file: require('@assets/animations/Safe.lottie'),
file: require<LottieViewProps['source']>('@assets/animations/Safe.lottie'),
w: 625,
h: 400,
backgroundColor: colors.ice500,
},
Magician: {
file: require('@assets/animations/Magician.lottie'),
file: require<LottieViewProps['source']>('@assets/animations/Magician.lottie'),
w: 853,
h: 480,
},
Update: {
file: require('@assets/animations/Update.lottie'),
file: require<LottieViewProps['source']>('@assets/animations/Update.lottie'),
w: variables.updateAnimationW,
h: variables.updateAnimationH,
},
Coin: {
file: require('@assets/animations/Coin.lottie'),
file: require<LottieViewProps['source']>('@assets/animations/Coin.lottie'),
w: 375,
h: 240,
backgroundColor: colors.yellow600,
},
Desk: {
file: require('@assets/animations/Desk.lottie'),
file: require<LottieViewProps['source']>('@assets/animations/Desk.lottie'),
w: 200,
h: 120,
backgroundColor: colors.blue700,
},
Plane: {
file: require('@assets/animations/Plane.lottie'),
file: require<LottieViewProps['source']>('@assets/animations/Plane.lottie'),
w: 180,
h: 200,
},
Expand Down
2 changes: 1 addition & 1 deletion src/components/MagicCodeInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ function MagicCodeInput(

// Fill the array with empty characters if there are no inputs.
if (focusedIndex === 0 && !hasInputs) {
numbers = Array(maxLength).fill(CONST.MAGIC_CODE_EMPTY_CHAR);
numbers = Array<string>(maxLength).fill(CONST.MAGIC_CODE_EMPTY_CHAR);

// Deletes the value of the previous input and focuses on it.
} else if (focusedIndex && focusedIndex !== 0) {
Expand Down
9 changes: 5 additions & 4 deletions src/components/OfflineWithFeedback.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {mapValues} from 'lodash';
import React, {useCallback} from 'react';
import type {ImageStyle, StyleProp, TextStyle, ViewStyle} from 'react-native';
import type {StyleProp, ViewStyle} from 'react-native';
import {View} from 'react-native';
import useNetwork from '@hooks/useNetwork';
import useStyleUtils from '@hooks/useStyleUtils';
Expand Down Expand Up @@ -60,7 +60,7 @@ type OfflineWithFeedbackProps = ChildrenProps & {
canDismissError?: boolean;
};

type StrikethroughProps = Partial<ChildrenProps> & {style: Array<ViewStyle | TextStyle | ImageStyle>};
type StrikethroughProps = Partial<ChildrenProps> & {style: AllStyles[]};

function OfflineWithFeedback({
pendingAction,
Expand Down Expand Up @@ -107,9 +107,10 @@ function OfflineWithFeedback({
return child;
}

const childProps: {children: React.ReactNode | undefined; style: AllStyles} = child.props;
type ChildComponentProps = ChildrenProps & {style?: AllStyles};
const childProps = child.props as ChildComponentProps;
const props: StrikethroughProps = {
style: StyleUtils.combineStyles(childProps.style, styles.offlineFeedback.deleted, styles.userSelectNone),
style: StyleUtils.combineStyles(childProps.style ?? [], styles.offlineFeedback.deleted, styles.userSelectNone),
};

if (childProps.children) {
Expand Down
Loading

0 comments on commit b49d5b8

Please sign in to comment.