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 13, 2024
1 parent b4db549 commit e977cc1
Show file tree
Hide file tree
Showing 88 changed files with 481 additions and 252 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
24 changes: 16 additions & 8 deletions frontend/src/api/prometheus/serving.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const useModelServingMetrics = (

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

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

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

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

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

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

const modelTrustyAIDIR = useQueryRangeResourceData(
biasMetricsAreaAvailable && type === PerformanceMetricType.MODEL,
(queries as { [key in ModelMetricType]: string })[ModelMetricType.TRUSTY_AI_DIR],
ModelMetricType.TRUSTY_AI_DIR in queries ? 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
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
6 changes: 3 additions & 3 deletions frontend/src/concepts/metrics/utils.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { SelectOptionObject } from '@patternfly/react-core/deprecated';
import { TimeframeTitle, RefreshIntervalTitle } from '~/concepts/metrics/types';
import { isEnumMember } from '~/utilities/utils';

export const isTimeframeTitle = (
timeframe: string | SelectOptionObject,
): timeframe is TimeframeTitle =>
Object.values(TimeframeTitle).includes(timeframe as TimeframeTitle);
): timeframe is TimeframeTitle => isEnumMember(timeframe.toString(), TimeframeTitle);

export const isRefreshIntervalTitle = (
refreshInterval: string | SelectOptionObject,
): refreshInterval is RefreshIntervalTitle =>
Object.values(RefreshIntervalTitle).includes(refreshInterval as RefreshIntervalTitle);
isEnumMember(refreshInterval.toString(), RefreshIntervalTitle);
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export const ModelRegistryContext = React.createContext<ModelRegistryContextType
hasCR: false,
crInitializing: false,
serverTimedOut: false,
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
apiState: { apiAvailable: false, api: null as unknown as ModelRegistryAPIState['api'] },
ignoreTimedOut: () => undefined,
refreshState: async () => undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,13 @@ const PipelineAndVersionContextProvider: React.FC<PipelineAndVersionContextProvi
}),
getResourcesForDeletion: () => ({
pipelines: selectedPipelines,
versions: (Object.values(selectedVersions) as SelectedVersion[])
.map((selectedVersion) =>
selectedVersion.versions.map((version) => ({
pipelineName: selectedVersion.pipelineName,
version,
})),
versions: Object.values(selectedVersions)
.map(
(selectedVersion) =>
selectedVersion?.versions.map((version) => ({
pipelineName: selectedVersion.pipelineName,
version,
})) ?? [],
)
.flat()
.filter((selection) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ export const PipelineRunArtifactSelect = <T,>({
isOpen={isOpen}
selected={selectedItemTitles}
onSelect={(_event, value) => {
if (selectedItemTitles.includes(value as string)) {
if (typeof value === 'string' && selectedItemTitles.includes(value)) {
setSelectedItemTitles(selectedItemTitles.filter((id) => id !== value));
} else {
setSelectedItemTitles([...selectedItemTitles, value as string]);
} else if (typeof value === 'string') {
setSelectedItemTitles([...selectedItemTitles, value]);
}
}}
onOpenChange={(nextOpen: boolean) => setIsOpen(nextOpen)}
Expand Down
Loading

0 comments on commit e977cc1

Please sign in to comment.