[ML] Improve some TS. (#202314)

## Summary

- Follow up to #175178 to fix some breaking TS changes after the TS
`v4.9.5` upgrade.
- Follow up to #182344 to replace `any` in `useCallback` with proper
types.
- Fixes #176123.

### Checklist

- [x] This was checked for breaking HTTP API changes, and any breaking
changes have been approved by the breaking-change committee. The
`release_note:breaking` label should be applied in these situations.
This commit is contained in:
Walter Rafelsberger 2024-12-05 17:26:26 +01:00 committed by GitHub
parent f1109cfcce
commit 5c6c4f44d3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 53 additions and 36 deletions

View file

@ -6,13 +6,16 @@
*/
import { useCallback, useRef, useState } from 'react';
import type { IKibanaSearchResponse } from '@kbn/search-types';
import type { IKibanaSearchRequest, IKibanaSearchResponse } from '@kbn/search-types';
import { isRunningResponse } from '@kbn/data-plugin/common';
import { tap } from 'rxjs';
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
export interface UseCancellableSearch {
runRequest: <RequestBody, ResponseType extends IKibanaSearchResponse>(
runRequest: <
RequestBody extends IKibanaSearchRequest,
ResponseType extends IKibanaSearchResponse
>(
requestBody: RequestBody,
options?: object
) => Promise<ResponseType | null>;
@ -26,13 +29,12 @@ export function useCancellableSearch(data: DataPublicPluginStart) {
const [isLoading, setIsFetching] = useState<boolean>(false);
const runRequest = useCallback(
<RequestBody, ResponseType extends IKibanaSearchResponse>(
<RequestBody extends IKibanaSearchRequest, ResponseType extends IKibanaSearchResponse>(
requestBody: RequestBody,
options = {}
): Promise<ResponseType | null> => {
return new Promise((resolve, reject) => {
data.search
// @ts-expect-error upgrade typescript v4.9.5
.search<RequestBody, ResponseType>(requestBody, {
abortSignal: abortController.current.signal,
...options,

View file

@ -9,7 +9,8 @@ import moment from 'moment';
import React from 'react';
import { act, render, fireEvent } from '@testing-library/react';
import type { Query } from '@kbn/es-query';
import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types';
import type { DataView } from '@kbn/data-views-plugin/public';
import type { TimefilterContract } from '@kbn/data-plugin/public';
import { __IntlProvider as IntlProvider } from '@kbn/i18n-react';
@ -48,9 +49,10 @@ describe('FullTimeRangeSelector', () => {
timeFieldName: '@timestamp',
} as unknown as DataView;
const query: Query = {
language: 'kuery',
query: 'region:us-east-1',
const query: QueryDslQueryContainer = {
term: {
region: 'us-east-1',
},
};
const props = {
@ -70,7 +72,6 @@ describe('FullTimeRangeSelector', () => {
const { getByText } = render(
<IntlProvider locale="en">
<DatePickerContextProvider {...mockDependencies}>
{/* @ts-expect-error upgrade typescript v4.9.5*/}
<FullTimeRangeSelector {...props} />
</DatePickerContextProvider>
</IntlProvider>
@ -99,7 +100,6 @@ describe('FullTimeRangeSelector', () => {
const { getByText } = render(
<IntlProvider locale="en">
<DatePickerContextProvider {...mockDependencies}>
{/* @ts-expect-error upgrade typescript v4.9.5*/}
<FullTimeRangeSelector {...props} />
</DatePickerContextProvider>
</IntlProvider>

View file

@ -51,7 +51,7 @@ export const InferenceFlyout: React.FC<GenericInferenceFlyoutProps> = ({
}, [inferenceEndpointError]);
const onChangingInferenceEndpoint = useCallback(
(value: any) => {
(value: string) => {
setInferenceEndpointId(value);
onInferenceEndpointChange(value);
},

View file

@ -10,7 +10,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { orderBy, isEqual } from 'lodash';
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import type { EuiTableSortingType } from '@elastic/eui';
import type { Criteria, EuiTableSortingType } from '@elastic/eui';
import { useEuiBackgroundColor, EuiBasicTable } from '@elastic/eui';
import type { SignificantItem } from '@kbn/ml-agg-utils';
@ -109,7 +109,7 @@ export const LogRateAnalysisResultsTable: FC<LogRateAnalysisResultsTableProps> =
groupFilter !== undefined
);
const onChange = useCallback((tableSettings: any) => {
const onChange = useCallback((tableSettings: Criteria<SignificantItem>) => {
if (tableSettings.page) {
const { index, size } = tableSettings.page;
setPageIndex(index);

View file

@ -9,7 +9,7 @@ import type { FC } from 'react';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { orderBy, isEqual } from 'lodash';
import type { EuiBasicTableColumn, EuiTableSortingType } from '@elastic/eui';
import type { EuiBasicTableColumn, EuiTableSortingType, Criteria } from '@elastic/eui';
import {
useEuiBackgroundColor,
EuiBadge,
@ -77,7 +77,7 @@ export const LogRateAnalysisResultsGroupsTable: FC<LogRateAnalysisResultsTablePr
const [pageIndex, setPageIndex] = useState(0);
const [pageSize, setPageSize] = useState(10);
const [sortField, setSortField] = useState<'docCount' | 'pValue'>(
const [sortField, setSortField] = useState<keyof GroupTableItem>(
zeroDocsFallback ? DEFAULT_SORT_FIELD_ZERO_DOCS_FALLBACK : DEFAULT_SORT_FIELD
);
const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>(
@ -247,7 +247,7 @@ export const LogRateAnalysisResultsGroupsTable: FC<LogRateAnalysisResultsTablePr
groupColumns.push(...columns);
const onChange = useCallback((tableSettings: any) => {
const onChange = useCallback((tableSettings: Criteria<GroupTableItem>) => {
if (tableSettings.page) {
const { index, size } = tableSettings.page;
setPageIndex(index);

View file

@ -6,7 +6,7 @@
*/
import { useCallback, useRef, useState } from 'react';
import type { IKibanaSearchResponse } from '@kbn/search-types';
import type { IKibanaSearchRequest, IKibanaSearchResponse } from '@kbn/search-types';
import { isRunningResponse } from '@kbn/data-plugin/common';
import { tap } from 'rxjs';
import { useAiopsAppContext } from './use_aiops_app_context';
@ -17,12 +17,11 @@ export function useCancellableSearch() {
const [isLoading, setIsFetching] = useState<boolean>(false);
const runRequest = useCallback(
<RequestBody, ResponseType extends IKibanaSearchResponse>(
<RequestBody extends IKibanaSearchRequest, ResponseType extends IKibanaSearchResponse>(
requestBody: RequestBody
): Promise<ResponseType | null> => {
return new Promise((resolve, reject) => {
data.search
// @ts-expect-error upgrade typescript v4.9.5
.search<RequestBody, ResponseType>(requestBody, {
abortSignal: abortController.current.signal,
})

View file

@ -506,9 +506,7 @@ const fetchComparisonDriftedData = async ({
);
fieldsWithNoOverlap.forEach((field) => {
// @ts-expect-error upgrade typescript v4.9.5
if (driftedResp.aggregations) {
// @ts-expect-error upgrade typescript v4.9.5
if (driftedResp?.aggregations) {
driftedResp.aggregations[`${field}_ks_test`] = {
// Setting -Infinity to represent astronomically small number
// which would be represented as < 0.000001 in table

View file

@ -226,7 +226,7 @@ const MlAnomalyAlertTrigger: FC<MlAnomalyAlertTriggerProps> = ({
<EuiSpacer size="m" />
<AdvancedSettings
value={advancedSettings}
onChange={useCallback((update: any) => {
onChange={useCallback((update: Partial<MlAnomalyDetectionAlertAdvancedSettings>) => {
Object.keys(update).forEach((k) => {
setRuleParams(k, update[k as keyof MlAnomalyDetectionAlertAdvancedSettings]);
});

View file

@ -18,7 +18,7 @@ import type { MlApi } from '../application/services/ml_api_service';
import { ALL_JOBS_SELECTION } from '../../common/constants/alerts';
import { LoadingIndicator } from '../application/components/loading_indicator';
interface JobSelection {
export interface JobSelection {
jobIds?: JobId[];
groupIds?: string[];
}

View file

@ -16,7 +16,7 @@ import type { RuleTypeParamsExpressionProps } from '@kbn/triggers-actions-ui-plu
import { isPopulatedObject } from '@kbn/ml-is-populated-object';
import { isDefined } from '@kbn/ml-is-defined';
import type { MlAnomalyDetectionJobsHealthRuleParams } from '../../../common/types/alerts';
import { JobSelectorControl } from '../job_selector';
import { JobSelectorControl, type JobSelection } from '../job_selector';
import { jobsApiProvider } from '../../application/services/ml_api_service/jobs';
import { HttpService } from '../../application/services/http_service';
import { useMlKibana } from '../../application/contexts/kibana';
@ -129,7 +129,7 @@ const AnomalyDetectionJobsHealthRuleTrigger: FC<MlAnomalyAlertTriggerProps> = ({
<JobSelectorControl
jobsAndGroupIds={excludeJobsAndGroupIds}
adJobsApiService={adJobsApiService}
onChange={useCallback((update: any) => {
onChange={useCallback((update: JobSelection) => {
const callback = onAlertParamChange('excludeJobs');
if (isPopulatedObject(update)) {
callback(update);

View file

@ -122,7 +122,7 @@ export const DecisionPathChart = ({
);
// if regression, guarantee up to num_precision significant digits without having it in scientific notation
// if classification, hide the numeric values since we only want to show the path
const tickFormatter = useCallback((d: any) => formatSingleValue(d, '').toString(), []);
const tickFormatter = useCallback((d: number) => formatSingleValue(d, '').toString(), []);
return (
<div data-test-subj="mlDFADecisionPathChart">

View file

@ -100,7 +100,7 @@ export const DataFrameAnalyticsList: FC<Props> = ({
const searchQueryText = pageState.queryText ?? '';
const setSearchQueryText = useCallback(
(value: any) => {
(value: string) => {
updatePageState({ queryText: value });
},
[updatePageState]

View file

@ -236,7 +236,7 @@ export const useExplorerData = (): [Partial<ExplorerState> | undefined, (d: any)
const explorerData$ = useMemo(() => loadExplorerData$.pipe(switchMap(loadExplorerData)), []);
const explorerData = useObservable(explorerData$);
const update = useCallback((c: any) => {
const update = useCallback((c: LoadExplorerDataConfig) => {
loadExplorerData$.next(c);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

View file

@ -465,7 +465,7 @@ export const AnomalyTimeline: FC<AnomalyTimelineProps> = React.memo(
<EuiFlexItem grow={true} css={{ maxWidth: '500px' }}>
<SeverityControl
value={severityUpdate ?? 0}
onChange={useCallback((update: any) => {
onChange={useCallback((update: number | undefined) => {
setSeverityUpdate(update);
}, [])}
/>

View file

@ -232,7 +232,7 @@ export const Explorer: FC<ExplorerUIProps> = ({
);
const onPanelWidthChange = useCallback(
(newSizes: any) => {
(newSizes: { [key: string]: number }) => {
setAnomalyExplorerPanelState({
mainPage: {
size: newSizes.mainPage,

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import React, { useCallback } from 'react';
import React, { useCallback, type ComponentProps } from 'react';
import {
EuiFieldNumber,
EuiFormRow,
@ -18,6 +18,12 @@ import { FormattedMessage } from '@kbn/i18n-react';
import type { FilterAggConfigRange } from '../types';
const BUTTON_SIZE = 40;
// The config prop of the component, to be used for the `updateConfig` function.
type FilterRangeFormConfig = ComponentProps<
Exclude<FilterAggConfigRange['aggTypeConfig']['FilterAggFormComponent'], undefined>
>['config'];
/**
* Form component for the range filter aggregation for number type fields.
*/
@ -31,7 +37,7 @@ export const FilterRangeForm: FilterAggConfigRange['aggTypeConfig']['FilterAggFo
const includeTo = config?.includeTo ?? false;
const updateConfig = useCallback(
(update: any) => {
(update: FilterRangeFormConfig) => {
onChange({
config: {
...config,

View file

@ -6,7 +6,14 @@
*/
import { debounce } from 'lodash';
import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react';
import React, {
useCallback,
useContext,
useEffect,
useMemo,
useState,
type ComponentProps,
} from 'react';
import useUpdateEffect from 'react-use/lib/useUpdateEffect';
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
@ -24,6 +31,11 @@ import { useToastNotifications } from '../../../../../../../app_dependencies';
import type { FilterAggConfigTerm } from '../types';
// The config prop of the component, to be used for the `updateConfig` function.
type FilterRangeFormConfig = ComponentProps<
Exclude<FilterAggConfigTerm['aggTypeConfig']['FilterAggFormComponent'], undefined>
>['config'];
/**
* Form component for the term filter aggregation.
*/
@ -51,7 +63,7 @@ export const FilterTermForm: FilterAggConfigTerm['aggTypeConfig']['FilterAggForm
}, []);
const updateConfig = useCallback(
(update: any) => {
(update: FilterRangeFormConfig) => {
onChange({
config: {
...config,

View file

@ -161,7 +161,7 @@ export function useLatestFunctionConfig(
}, [dataView, data.search.aggs, runtimeMappings]);
const updateLatestFunctionConfig = useCallback(
(update: any) =>
(update: Partial<LatestFunctionConfigUI>) =>
setLatestFunctionConfig({
...config,
...update,