diff --git a/.eslintrc.js b/.eslintrc.js index 02c407cba..77547d879 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -45,6 +45,11 @@ module.exports = { rules: { eqeqeq: 'error', 'prettier/prettier': ['error', prettier], + // TypeScript can infer this significantly better than eslint ever can. + 'react/prop-types': 0, + 'react/display-name': 0, + '@typescript-eslint/no-explicit-any': 0, + '@typescript-eslint/no-non-null-assertion': 0, // This setup is required to avoid a spam of errors when running eslint about React being // used before it is defined. // diff --git a/resources/scripts/components/NavigationBar.tsx b/resources/scripts/components/NavigationBar.tsx index e3c9c98b7..89180b14b 100644 --- a/resources/scripts/components/NavigationBar.tsx +++ b/resources/scripts/components/NavigationBar.tsx @@ -40,7 +40,7 @@ export default () => { const onTriggerLogout = () => { setIsLoggingOut(true); http.post('/auth/logout').finally(() => { - // @ts-ignore + // @ts-expect-error this is valid window.location = '/'; }); }; diff --git a/resources/scripts/components/auth/LoginCheckpointContainer.tsx b/resources/scripts/components/auth/LoginCheckpointContainer.tsx index 21efeb931..66a6fb8f4 100644 --- a/resources/scripts/components/auth/LoginCheckpointContainer.tsx +++ b/resources/scripts/components/auth/LoginCheckpointContainer.tsx @@ -77,7 +77,7 @@ const EnhancedForm = withFormik({ loginCheckpoint(location.state?.token || '', code, recoveryCode) .then((response) => { if (response.complete) { - // @ts-ignore + // @ts-expect-error this is valid window.location = response.intended || '/'; return; } diff --git a/resources/scripts/components/auth/LoginContainer.tsx b/resources/scripts/components/auth/LoginContainer.tsx index d848ff602..453a27ecc 100644 --- a/resources/scripts/components/auth/LoginContainer.tsx +++ b/resources/scripts/components/auth/LoginContainer.tsx @@ -46,7 +46,7 @@ const LoginContainer = ({ history }: RouteComponentProps) => { login({ ...values, recaptchaData: token }) .then((response) => { if (response.complete) { - // @ts-ignore + // @ts-expect-error this is valid window.location = response.intended || '/'; return; } diff --git a/resources/scripts/components/auth/ResetPasswordContainer.tsx b/resources/scripts/components/auth/ResetPasswordContainer.tsx index 1770801aa..a6f346aed 100644 --- a/resources/scripts/components/auth/ResetPasswordContainer.tsx +++ b/resources/scripts/components/auth/ResetPasswordContainer.tsx @@ -33,7 +33,7 @@ export default ({ match, location }: RouteComponentProps<{ token: string }>) => clearFlashes(); performPasswordReset(email, { token: match.params.token, password, passwordConfirmation }) .then(() => { - // @ts-ignore + // @ts-expect-error this is valid window.location = '/'; }) .catch((error) => { @@ -57,7 +57,7 @@ export default ({ match, location }: RouteComponentProps<{ token: string }>) => .min(8, 'Your new password should be at least 8 characters in length.'), passwordConfirmation: string() .required('Your new password does not match.') - // @ts-ignore + // @ts-expect-error this is valid .oneOf([ref('password'), null], 'Your new password does not match.'), })} > diff --git a/resources/scripts/components/dashboard/ServerRow.tsx b/resources/scripts/components/dashboard/ServerRow.tsx index a016c07d1..8336e67f8 100644 --- a/resources/scripts/components/dashboard/ServerRow.tsx +++ b/resources/scripts/components/dashboard/ServerRow.tsx @@ -47,8 +47,10 @@ const StatusIndicatorBox = styled(GreyRowBox)<{ $status: ServerPowerState | unde } `; +type Timer = ReturnType; + export default ({ server, className }: { server: Server; className?: string }) => { - const interval = useRef(null); + const interval = useRef(null) as React.MutableRefObject; const [isSuspended, setIsSuspended] = useState(server.status === 'suspended'); const [stats, setStats] = useState(null); @@ -67,7 +69,6 @@ export default ({ server, className }: { server: Server; className?: string }) = if (isSuspended) return; getStats().then(() => { - // @ts-ignore interval.current = setInterval(() => getStats(), 30000); }); diff --git a/resources/scripts/components/dashboard/forms/UpdatePasswordForm.tsx b/resources/scripts/components/dashboard/forms/UpdatePasswordForm.tsx index 7153bfda5..a82bfa1b7 100644 --- a/resources/scripts/components/dashboard/forms/UpdatePasswordForm.tsx +++ b/resources/scripts/components/dashboard/forms/UpdatePasswordForm.tsx @@ -40,7 +40,7 @@ export default () => { clearFlashes('account:password'); updateAccountPassword({ ...values }) .then(() => { - // @ts-ignore + // @ts-expect-error this is valid window.location = '/auth/login'; }) .catch((error) => diff --git a/resources/scripts/components/elements/CodemirrorEditor.tsx b/resources/scripts/components/elements/CodemirrorEditor.tsx index aa1611a4c..99a7b5e85 100644 --- a/resources/scripts/components/elements/CodemirrorEditor.tsx +++ b/resources/scripts/components/elements/CodemirrorEditor.tsx @@ -169,8 +169,7 @@ export default ({ style, initialContent, filename, mode, fetchContent, onContent autocorrect: false, autocapitalize: false, lint: false, - // This property is actually used, the d.ts file for CodeMirror is incorrect. - // @ts-ignore + // @ts-expect-error this property is actually used, the d.ts file for CodeMirror is incorrect. autoCloseBrackets: true, matchBrackets: true, gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'], diff --git a/resources/scripts/components/elements/Icon.tsx b/resources/scripts/components/elements/Icon.tsx index 14aad22e5..465d5a52d 100644 --- a/resources/scripts/components/elements/Icon.tsx +++ b/resources/scripts/components/elements/Icon.tsx @@ -9,9 +9,7 @@ interface Props { } const Icon = ({ icon, className, style }: Props) => { - let [width, height, , , paths] = icon.icon; - - paths = Array.isArray(paths) ? paths : [paths]; + const [width, height, , , paths] = icon.icon; return ( { className={className} style={style} > - {paths.map((path, index) => ( + {(Array.isArray(paths) ? paths : [paths]).map((path, index) => ( ))} diff --git a/resources/scripts/components/elements/ProgressBar.tsx b/resources/scripts/components/elements/ProgressBar.tsx index 9bef2b7a3..c94ae80f3 100644 --- a/resources/scripts/components/elements/ProgressBar.tsx +++ b/resources/scripts/components/elements/ProgressBar.tsx @@ -11,9 +11,11 @@ const BarFill = styled.div` box-shadow: 0 -2px 10px 2px hsl(178, 78%, 57%); `; +type Timer = ReturnType; + export default () => { - const interval = useRef(null); - const timeout = useRef(null); + const interval = useRef(null) as React.MutableRefObject; + const timeout = useRef(null) as React.MutableRefObject; const [visible, setVisible] = useState(false); const progress = useStoreState((state) => state.progress.progress); const continuous = useStoreState((state) => state.progress.continuous); @@ -30,7 +32,6 @@ export default () => { setVisible((progress || 0) > 0); if (progress === 100) { - // @ts-ignore timeout.current = setTimeout(() => setProgress(undefined), 500); } }, [progress]); @@ -52,8 +53,7 @@ export default () => { if ((progress || 0) >= 90) { setProgress(90); } else { - // @ts-ignore - interval.current = setTimeout(() => setProgress(progress + randomInt(1, 5)), 500); + interval.current = setTimeout(() => setProgress((progress || 0) + randomInt(1, 5)), 500); } } }, [progress, continuous]); diff --git a/resources/scripts/components/elements/button/Button.tsx b/resources/scripts/components/elements/button/Button.tsx index 17569d162..61ee96311 100644 --- a/resources/scripts/components/elements/button/Button.tsx +++ b/resources/scripts/components/elements/button/Button.tsx @@ -28,12 +28,12 @@ const Button = forwardRef( ); const TextButton = forwardRef(({ className, ...props }, ref) => ( - // @ts-expect-error + // @ts-expect-error not sure how to get this correct