Skip to content

Commit

Permalink
first round of updates to disable type assertions
Browse files Browse the repository at this point in the history
  • Loading branch information
rsun19 committed Jun 18, 2024
1 parent 48a6201 commit cb9ac68
Show file tree
Hide file tree
Showing 87 changed files with 367 additions and 267 deletions.
12 changes: 12 additions & 0 deletions frontend/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,18 @@
}
]
}
},
{
"files": ["*.ts", "*.tsx"],
"excludedFiles": ["**/__mocks__/**", "**/__tests__/**"],
"rules": {
"@typescript-eslint/consistent-type-assertions": [
"error",
{
"assertionStyle": "never"
}
]
}
}
]
}
7 changes: 3 additions & 4 deletions frontend/src/__tests__/unit/testUtils/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ export const renderHook = <
options?: RenderHookOptions<Props, Q, Container, BaseElement>,
): RenderHookResultExt<Result, Props> => {
let updateCount = 0;
let prevResult: Result | undefined;
let currentResult: Result | undefined;
let prevResult: Result;
let currentResult: Result;

const renderResult = renderHookRTL((props) => {
updateCount++;
Expand All @@ -80,8 +80,7 @@ export const renderHook = <
const renderResultExt: RenderHookResultExt<Result, Props> = {
...renderResult,

getPreviousResult: () =>
updateCount > 1 ? (prevResult as Result) : renderResult.result.current,
getPreviousResult: () => (updateCount > 1 ? prevResult : renderResult.result.current),

getUpdateCount: () => updateCount,

Expand Down
3 changes: 2 additions & 1 deletion frontend/src/api/errorUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { K8sStatus } from '@openshift/dynamic-plugin-sdk-utils';
import { AxiosError } from 'axios';

export const isK8sStatus = (data: unknown): data is K8sStatus =>
(data as K8sStatus).kind === 'Status';
typeof data === 'object' && data !== null && 'kind' in data && data.kind === 'Status';

export class K8sStatusError extends Error {
public statusObject: K8sStatus;
Expand All @@ -18,6 +18,7 @@ const isAxiosErrorWithResponseMessage = (
error?: Error | AxiosError,
): error is AxiosError<{ message: string }> =>
Boolean(
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
error && typeof (error as AxiosError<{ message: string }>).response?.data.message === 'string',
);

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/api/modelRegistry/errorUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ModelRegistryError } from '~/concepts/modelRegistry/types';
import { isCommonStateError } from '~/utilities/useFetchState';

const isError = (e: unknown): e is ModelRegistryError =>
['code', 'message'].every((key) => key in (e as ModelRegistryError));
typeof e === 'object' && e !== null && ['code', 'message'].every((key) => key in e);

export const handleModelRegistryFailures = <T>(promise: Promise<T>): Promise<T> =>
promise
Expand Down
6 changes: 4 additions & 2 deletions frontend/src/api/pipelines/errorUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ type ResultErrorKF = {
};

const isErrorKF = (e: unknown): e is ErrorKF =>
['error', 'code', 'message'].every((key) => key in (e as ErrorKF));
typeof e === 'object' && e !== null && ['error', 'code', 'message'].every((key) => key in e);

const isErrorDetailsKF = (result: unknown): result is ResultErrorKF =>
['error_details', 'error_message'].every((key) => key in (result as ResultErrorKF));
typeof result === 'object' &&
result !== null &&
['error_details', 'error_message'].every((key) => key in result);

export const handlePipelineFailures = <T>(promise: Promise<T>): Promise<T> =>
promise
Expand Down
36 changes: 23 additions & 13 deletions frontend/src/api/prometheus/serving.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { RefreshIntervalValue } from '~/concepts/metrics/const';
import useRefreshInterval from '~/utilities/useRefreshInterval';
import { SupportedArea, useIsAreaAvailable } from '~/concepts/areas';
import { PROMETHEUS_BIAS_PATH } from '~/api/prometheus/const';
import { EitherNotBoth } from '~/typeHelpers';
import useQueryRangeResourceData from './useQueryRangeResourceData';
import {
defaultResponsePredicate,
Expand All @@ -22,17 +23,26 @@ import {

export const useModelServingMetrics = (
type: PerformanceMetricType,
queries: { [key in ModelMetricType]: string } | { [key in ServerMetricType]: string },
queries: EitherNotBoth<
{ [key in ModelMetricType]: string },
{ [key in ServerMetricType]: string }
>,
timeframe: TimeframeTitle,
lastUpdateTime: number,
setLastUpdateTime: (time: number) => void,
refreshInterval: RefreshIntervalTitle,
namespace: string,
): {
data: Record<
ServerMetricType | ModelMetricType,
ContextResourceData<PrometheusQueryRangeResultValue | PrometheusQueryRangeResponseDataResult>
>;
data: {
[ServerMetricType.REQUEST_COUNT]: ContextResourceData<PrometheusQueryRangeResultValue>;
[ServerMetricType.AVG_RESPONSE_TIME]: ContextResourceData<PrometheusQueryRangeResponseDataResult>;
[ServerMetricType.CPU_UTILIZATION]: ContextResourceData<PrometheusQueryRangeResultValue>;
[ServerMetricType.MEMORY_UTILIZATION]: ContextResourceData<PrometheusQueryRangeResultValue>;
[ModelMetricType.REQUEST_COUNT_FAILED]: ContextResourceData<PrometheusQueryRangeResultValue>;
[ModelMetricType.REQUEST_COUNT_SUCCESS]: ContextResourceData<PrometheusQueryRangeResultValue>;
[ModelMetricType.TRUSTY_AI_SPD]: ContextResourceData<PrometheusQueryRangeResponseDataResult>;
[ModelMetricType.TRUSTY_AI_DIR]: ContextResourceData<PrometheusQueryRangeResponseDataResult>;
};
refresh: () => void;
} => {
const [end, setEnd] = React.useState(lastUpdateTime);
Expand All @@ -43,7 +53,7 @@ export const useModelServingMetrics = (

const serverRequestCount = useQueryRangeResourceData(
performanceMetricsAreaAvailable && type === PerformanceMetricType.SERVER,
(queries as { [key in ServerMetricType]: string })[ServerMetricType.REQUEST_COUNT],
queries[ServerMetricType.REQUEST_COUNT] ?? '',
end,
timeframe,
defaultResponsePredicate,
Expand All @@ -53,7 +63,7 @@ export const useModelServingMetrics = (
const serverAverageResponseTime =
useQueryRangeResourceData<PrometheusQueryRangeResponseDataResult>(
performanceMetricsAreaAvailable && type === PerformanceMetricType.SERVER,
(queries as { [key in ServerMetricType]: string })[ServerMetricType.AVG_RESPONSE_TIME],
queries[ServerMetricType.AVG_RESPONSE_TIME] ?? '',
end,
timeframe,
prometheusQueryRangeResponsePredicate,
Expand All @@ -62,7 +72,7 @@ export const useModelServingMetrics = (

const serverCPUUtilization = useQueryRangeResourceData(
performanceMetricsAreaAvailable && type === PerformanceMetricType.SERVER,
(queries as { [key in ServerMetricType]: string })[ServerMetricType.CPU_UTILIZATION],
queries[ServerMetricType.CPU_UTILIZATION] ?? '',
end,
timeframe,
defaultResponsePredicate,
Expand All @@ -71,7 +81,7 @@ export const useModelServingMetrics = (

const serverMemoryUtilization = useQueryRangeResourceData(
performanceMetricsAreaAvailable && type === PerformanceMetricType.SERVER,
(queries as { [key in ServerMetricType]: string })[ServerMetricType.MEMORY_UTILIZATION],
queries[ServerMetricType.MEMORY_UTILIZATION] ?? '',
end,
timeframe,
defaultResponsePredicate,
Expand All @@ -80,7 +90,7 @@ export const useModelServingMetrics = (

const modelRequestSuccessCount = useQueryRangeResourceData(
performanceMetricsAreaAvailable && type === PerformanceMetricType.MODEL,
(queries as { [key in ModelMetricType]: string })[ModelMetricType.REQUEST_COUNT_SUCCESS],
queries[ModelMetricType.REQUEST_COUNT_SUCCESS] ?? '',
end,
timeframe,
defaultResponsePredicate,
Expand All @@ -89,7 +99,7 @@ export const useModelServingMetrics = (

const modelRequestFailedCount = useQueryRangeResourceData(
performanceMetricsAreaAvailable && type === PerformanceMetricType.MODEL,
(queries as { [key in ModelMetricType]: string })[ModelMetricType.REQUEST_COUNT_FAILED],
queries[ModelMetricType.REQUEST_COUNT_FAILED] ?? '',
end,
timeframe,
defaultResponsePredicate,
Expand All @@ -98,7 +108,7 @@ export const useModelServingMetrics = (

const modelTrustyAISPD = useQueryRangeResourceData(
biasMetricsAreaAvailable && type === PerformanceMetricType.MODEL,
(queries as { [key in ModelMetricType]: string })[ModelMetricType.TRUSTY_AI_SPD],
queries[ModelMetricType.TRUSTY_AI_SPD] ?? '',
end,
timeframe,
prometheusQueryRangeResponsePredicate,
Expand All @@ -108,7 +118,7 @@ export const useModelServingMetrics = (

const modelTrustyAIDIR = useQueryRangeResourceData(
biasMetricsAreaAvailable && type === PerformanceMetricType.MODEL,
(queries as { [key in ModelMetricType]: string })[ModelMetricType.TRUSTY_AI_DIR],
queries[ModelMetricType.TRUSTY_AI_DIR] ?? '',
end,
timeframe,
prometheusQueryRangeResponsePredicate,
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/api/trustyai/errorUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ type TrustyAIClientErrorViolation = {
};

const isTrustyAIClientError = (e: unknown): e is TrustyAIClientError =>
typeof e === 'object' &&
['title', 'status', 'violations'].every((key) => key in (e as TrustyAIClientError));
typeof e === 'object' && e !== null && ['title', 'status', 'violations'].every((key) => key in e);

export const handleTrustyAIFailures = <T>(promise: Promise<T>): Promise<T> =>
promise.then((result) => {
Expand Down
10 changes: 2 additions & 8 deletions frontend/src/app/AppContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,7 @@ type AppContextProps = {
storageClasses: StorageClassKind[];
};

const defaultAppContext: AppContextProps = {
buildStatuses: [],
// At runtime dashboardConfig is never null -- DO NOT DO THIS usually
dashboardConfig: null as unknown as DashboardConfigKind,
storageClasses: [] as StorageClassKind[],
};

export const AppContext = React.createContext(defaultAppContext);
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
export const AppContext = React.createContext({} as AppContextProps);

export const useAppContext = (): AppContextProps => React.useContext(AppContext);
4 changes: 2 additions & 2 deletions frontend/src/components/DocCardBadges.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { QuickStartContext, QuickStartContextValues } from '@patternfly/quicksta
import { OdhDocument, OdhDocumentType } from '~/types';
import { getQuickStartCompletionStatus, CompletionStatusEnum } from '~/utilities/quickStartUtils';
import { DOC_TYPE_TOOLTIPS } from '~/utilities/const';
import { getLabelColorForDocType, getDuration } from '~/utilities/utils';
import { getLabelColorForDocType, getDuration, asEnumMember } from '~/utilities/utils';
import { DOC_TYPE_LABEL } from '~/pages/learningCenter/const';

import './OdhCard.scss';
Expand All @@ -19,7 +19,7 @@ const DocCardBadges: React.FC<DocCardBadgesProps> = ({ odhDoc }) => {
const [completionStatus, setCompletionStatus] = React.useState<
CompletionStatusEnum | undefined
>();
const docType = odhDoc.spec.type as OdhDocumentType;
const docType = asEnumMember(odhDoc.spec.type, OdhDocumentType) ?? OdhDocumentType.Documentation;
const docName = odhDoc.metadata.name;
const duration = odhDoc.spec.durationMinutes;

Expand Down
12 changes: 6 additions & 6 deletions frontend/src/components/FilterSidePanelCategoryItem.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as React from 'react';
import { css } from '@patternfly/react-styles';
import { Checkbox } from '@patternfly/react-core';
import { Checkbox, CheckboxProps } from '@patternfly/react-core';

export interface FilterSidePanelCategoryItemProps extends React.HTMLProps<HTMLDivElement> {
export interface FilterSidePanelCategoryItemProps {
id: string;
/** Children nodes */
children: React.ReactNode;
Expand All @@ -13,7 +13,7 @@ export interface FilterSidePanelCategoryItemProps extends React.HTMLProps<HTMLDi
/** Optional count of the items matching the filter */
count?: number | null;
/** Callback for a click on the Filter Item Checkbox */
onClick?: (event: React.SyntheticEvent<HTMLElement>) => void;
onChange?: CheckboxProps['onChange'];
/** Flag to show if the Filter Item Checkbox is checked. */
checked?: boolean;
/** Title of the checkbox */
Expand All @@ -27,7 +27,7 @@ const FilterSidePanelCategoryItem: React.FunctionComponent<FilterSidePanelCatego
className = '',
icon = null,
count = null,
onClick,
onChange,
checked = false,
title = '',
...props
Expand All @@ -43,8 +43,8 @@ const FilterSidePanelCategoryItem: React.FunctionComponent<FilterSidePanelCatego
return (
<div id={id} className={classes} {...props}>
<Checkbox
onClick={onClick}
checked={checked}
onChange={onChange}
isChecked={checked}
data-testid={id}
id={`${id}--check-box`}
label={label}
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/components/OdhDocListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ExternalLinkAltIcon } from '@patternfly/react-icons';
import { OdhDocument, OdhDocumentType } from '~/types';
import { getQuickStartLabel, launchQuickStart } from '~/utilities/quickStartUtils';
import { DOC_TYPE_TOOLTIPS } from '~/utilities/const';
import { getDuration } from '~/utilities/utils';
import { asEnumMember, getDuration } from '~/utilities/utils';
import { useQuickStartCardSelected } from './useQuickStartCardSelected';
import FavoriteButton from './FavoriteButton';

Expand All @@ -26,7 +26,8 @@ const OdhDocListItem: React.FC<OdhDocCardProps> = ({ odhDoc, favorite, updateFav
};

const renderTypeBadge = () => {
const docType = odhDoc.spec.type as OdhDocumentType;
const docType =
asEnumMember(odhDoc.spec.type, OdhDocumentType) ?? OdhDocumentType.Documentation;
const typeBadgeClasses = classNames('odh-list-item__partner-badge odh-m-doc', {
'odh-m-documentation': docType === OdhDocumentType.Documentation,
'odh-m-tutorial': docType === OdhDocumentType.Tutorial,
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/components/ToastNotification.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Alert, AlertActionCloseButton, AlertVariant } from '@patternfly/react-c
import { AppNotification } from '~/redux/types';
import { ackNotification, hideNotification } from '~/redux/actions/actions';
import { useAppDispatch } from '~/redux/hooks';
import { asEnumMember } from '~/utilities/utils';

const TOAST_NOTIFICATION_TIMEOUT = 8 * 1000;

Expand Down Expand Up @@ -36,7 +37,7 @@ const ToastNotification: React.FC<ToastNotificationProps> = ({ notification }) =

return (
<Alert
variant={notification.status as AlertVariant}
variant={asEnumMember(notification.status, AlertVariant) ?? undefined}
title={notification.title}
actionClose={
<AlertActionCloseButton onClose={() => dispatch(ackNotification(notification))} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export const useBrowserStorage = <T,>(
[isSessionStorage, jsonify, setJSONValue, setStringValue, storageKey],
);

// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
return [(getValue(storageKey, jsonify, isSessionStorage) as T) ?? defaultValue, setValue];
};

Expand Down
2 changes: 2 additions & 0 deletions frontend/src/components/table/useTableColumnSort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@ const useTableColumnSort = <T>(
return 0;
}

// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const dataValueA = a[columnField.field as keyof T];
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const dataValueB = b[columnField.field as keyof T];
if (typeof dataValueA === 'string' && typeof dataValueB === 'string') {
return dataValueA.localeCompare(dataValueB);
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/concepts/areas/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ const getFlags = (dashboardConfigSpec: DashboardConfigKind['spec']): FlagState =
typeof value === 'boolean';

return {
...Object.keys(flags).reduce<FlagState>((acc, key) => {
const value = flags[key as FeatureFlag];
...Object.entries(flags).reduce<FlagState>((acc, [key, value]) => {
if (isFeatureFlag(key, value)) {
acc[key] = key.startsWith('disable') ? !value : value;
}
Expand Down
6 changes: 5 additions & 1 deletion frontend/src/concepts/dashboard/DashboardSearchField.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react';
import { InputGroup, SearchInput, InputGroupItem } from '@patternfly/react-core';
import SimpleDropdownSelect from '~/components/SimpleDropdownSelect';
import { asEnumMember } from '~/utilities/utils';

// List all the possible search fields here
export enum SearchType {
Expand Down Expand Up @@ -48,7 +49,10 @@ const DashboardSearchField: React.FC<DashboardSearchFieldProps> = ({
}))}
value={searchType}
onChange={(key) => {
onSearchTypeChange(key as SearchType);
const enumMember = asEnumMember(key, SearchType);
if (enumMember !== null) {
onSearchTypeChange(enumMember);
}
}}
icon={icon}
/>
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/concepts/distributedWorkloads/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
convertToUnit,
} from '~/utilities/valueUnits';
import { WorkloadWithUsage } from '~/api';
import { isEnumMember } from '~/utilities/utils';

export enum WorkloadStatusType {
Pending = 'Pending',
Expand Down Expand Up @@ -166,7 +167,7 @@ export const getWorkloadName = (workload: WorkloadKind): string =>
workload.metadata?.name || 'Unnamed';

export const isKnownWorkloadOwnerType = (s: string): s is WorkloadOwnerType =>
(Object.values(WorkloadOwnerType) as string[]).includes(s);
isEnumMember(s, WorkloadOwnerType);

export const getWorkloadOwner = (
workload: WorkloadKind,
Expand Down
1 change: 1 addition & 0 deletions frontend/src/concepts/docResources/docUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const getQuickStartDocs = (
// Get doc cards for the quick starts
const docs: OdhDocument[] = quickStarts.map(
(quickStart) =>
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
_.merge({}, quickStart, {
spec: {
type: OdhDocumentType.QuickStart,
Expand Down
Loading

0 comments on commit cb9ac68

Please sign in to comment.