From 6fb4cadb815ba5e6b2eeefea239620c988106549 Mon Sep 17 00:00:00 2001 From: Stephan Lee Date: Wed, 15 Dec 2021 09:58:08 -0800 Subject: [PATCH] type: enable `exactOptionalPropertyTypes` option (#5459) Before this change, below held true: ```ts interface Foo { bar?: number; } // Legal const foo1: Foo = {}; // Legal const foo2: Foo = {bar: undefined}; ``` After this change, ```ts interface Foo { bar?: number; baz: number|undefined; } // Illegal; `bar` cannot be `undefined` and must be number. const foo1: Foo = {bar: undefined, baz: undefined}; // Illegal; `baz` property must exist. Must be one of `number` of // `undefined`. const foo2: Foo = {}; // Legal; `bar` property does not exist while `baz` is specified. const foo3: Foo = {baz: undefined}; ``` When a property is defined as `?:`, it does not mean that the property can be `undefined` but it means a property can be omitted altogether or it must exist with the value of the type as defined. As such, when a property is written with `undefined`, the value type must explicitly allow `undefined` like `baz` example above. --- .../store/debugger_selectors.ts | 4 +- .../views/graph/graph_container_test.ts | 20 ++----- tensorboard/webapp/alert/alert_action_test.ts | 8 ++- .../webapp/alert/store/alert_reducers.ts | 15 ++--- .../webapp/alert/store/alert_reducers_test.ts | 1 - .../webapp/app_routing/route_config.ts | 10 +++- .../webapp/app_routing/route_config_test.ts | 9 ++- .../experiments/store/experiments_reducers.ts | 3 +- .../webapp/experiments/store/testing.ts | 4 +- tensorboard/webapp/metrics/actions/index.ts | 2 +- tensorboard/webapp/metrics/effects/index.ts | 10 +++- .../metrics/effects/metrics_effects_test.ts | 13 ++--- .../metrics/store/metrics_reducers_test.ts | 14 ++--- .../views/card_renderer/card_lazy_loader.ts | 10 +++- .../persistent_settings_data_source.ts | 57 ++++++++++++++----- .../plugins/npmi/actions/npmi_actions.ts | 2 +- .../npmi/data_source/npmi_data_source.ts | 2 +- .../plugins/npmi/store/npmi_reducers.ts | 1 + .../webapp/plugins/npmi/store/npmi_types.ts | 2 +- .../webapp/plugins/npmi/testing/index.ts | 1 + .../runs/views/runs_table/runs_table_test.ts | 4 +- .../settings/_redux/settings_reducers.ts | 6 +- .../webapp_data_source/tb_http_client.ts | 4 +- .../intersection_observer_directive.ts | 2 +- .../line_chart_interactive_utils_test.ts | 13 +++-- tsconfig.json | 1 + 26 files changed, 133 insertions(+), 85 deletions(-) diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors.ts index 2567694f8a1..e0ce30b7c80 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/store/debugger_selectors.ts @@ -342,7 +342,7 @@ export const getFocusedGraphOpInputs = createSelector( ...inputSpec, }; if (graph.has(inputSpec.op_name)) { - spec.data = graph.get(inputSpec.op_name); + spec.data = graph.get(inputSpec.op_name)!; } return spec; }); @@ -427,7 +427,7 @@ export const getFocusedGraphOpConsumers = createSelector( return slotConsumers.map((consumerSpec) => { const spec: GraphOpConsumerSpec = {...consumerSpec}; if (graph.has(consumerSpec.op_name)) { - spec.data = graph.get(consumerSpec.op_name); + spec.data = graph.get(consumerSpec.op_name)!; } return spec; }); diff --git a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph/graph_container_test.ts b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph/graph_container_test.ts index 2ba13331a44..0cea58f2a38 100644 --- a/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph/graph_container_test.ts +++ b/tensorboard/plugins/debugger_v2/tf_debugger_v2_plugin/views/graph/graph_container_test.ts @@ -129,20 +129,12 @@ describe('Graph Container', () => { }, ]; store.overrideSelector(getFocusedGraphOpInfo, op2); - store.overrideSelector(getFocusedGraphOpInputs, [ - { - ...op2.inputs[0], - data: neighborDataAvailable ? op1 : undefined, - }, - ]); - store.overrideSelector(getFocusedGraphOpConsumers, [ - [ - { - ...op2.consumers[0][0], - data: neighborDataAvailable ? op3 : undefined, - }, - ], - ]); + const input = {...op2.inputs[0]}; + if (neighborDataAvailable) input.data = op1; + store.overrideSelector(getFocusedGraphOpInputs, [input]); + const consumer = {...op2.consumers[0][0]}; + if (neighborDataAvailable) consumer.data = op3; + store.overrideSelector(getFocusedGraphOpConsumers, [[consumer]]); fixture.detectChanges(); diff --git a/tensorboard/webapp/alert/alert_action_test.ts b/tensorboard/webapp/alert/alert_action_test.ts index 5c3d7d7e147..45d0e0ebaad 100644 --- a/tensorboard/webapp/alert/alert_action_test.ts +++ b/tensorboard/webapp/alert/alert_action_test.ts @@ -43,7 +43,9 @@ describe('alert_effects', () => { actionCreator: alertActionOccurred, alertFromAction: (action: Action) => { if (shouldReportAlert) { - return {localizedMessage: 'alert details'}; + return { + localizedMessage: 'alert details', + }; } return null; }, @@ -67,7 +69,9 @@ describe('alert_effects', () => { actions$.next(alertActionOccurred); expect(recordedActions).toEqual([ - alertActions.alertReported({localizedMessage: 'alert details'}), + alertActions.alertReported({ + localizedMessage: 'alert details', + }), ]); }); diff --git a/tensorboard/webapp/alert/store/alert_reducers.ts b/tensorboard/webapp/alert/store/alert_reducers.ts index 2b0a437204e..fc594bec463 100644 --- a/tensorboard/webapp/alert/store/alert_reducers.ts +++ b/tensorboard/webapp/alert/store/alert_reducers.ts @@ -14,6 +14,7 @@ limitations under the License. ==============================================================================*/ import {Action, createReducer, on} from '@ngrx/store'; import * as actions from '../actions'; +import {AlertInfo} from '../types'; import {AlertState} from './alert_types'; const initialState: AlertState = { @@ -25,14 +26,14 @@ const reducer = createReducer( on( actions.alertReported, (state: AlertState, {localizedMessage, followupAction}): AlertState => { - return { - ...state, - latestAlert: { - localizedMessage, - followupAction, - created: Date.now(), - }, + const latestAlert: AlertInfo = { + localizedMessage, + created: Date.now(), }; + if (followupAction) { + latestAlert.followupAction = followupAction; + } + return {...state, latestAlert}; } ) ); diff --git a/tensorboard/webapp/alert/store/alert_reducers_test.ts b/tensorboard/webapp/alert/store/alert_reducers_test.ts index 6eef7713ea1..b7be8e252d8 100644 --- a/tensorboard/webapp/alert/store/alert_reducers_test.ts +++ b/tensorboard/webapp/alert/store/alert_reducers_test.ts @@ -41,7 +41,6 @@ describe('alert_reducers', () => { const state2 = alertReducers.reducers(state1, action1); expect(state2.latestAlert!).toEqual({ localizedMessage: 'Foo1 failed', - followupAction: undefined, created: 123, }); diff --git a/tensorboard/webapp/app_routing/route_config.ts b/tensorboard/webapp/app_routing/route_config.ts index b3f31f75039..443a0dbc1cc 100644 --- a/tensorboard/webapp/app_routing/route_config.ts +++ b/tensorboard/webapp/app_routing/route_config.ts @@ -31,7 +31,7 @@ interface PositiveMatch { params: RouteParams; pathParts: string[]; isRedirection: boolean; - redirectionQueryParams?: SerializableQueryParams; + redirectionQueryParams: SerializableQueryParams | undefined; } type Match = NegativeMatch | PositiveMatch; @@ -172,6 +172,7 @@ abstract class RouteConfigMatcher { params: combinedParams, pathParts, isRedirection: false, + redirectionQueryParams: undefined, }; } @@ -186,6 +187,7 @@ abstract class RouteConfigMatcher { params, pathParts, isRedirection: false, + redirectionQueryParams: undefined, }; } @@ -243,6 +245,7 @@ class StaticRedirectionRouteConfigMatcher extends RouteConfigMatcher { params: match.params, pathParts: newPathParts, isRedirection: true, + redirectionQueryParams: undefined, }; } } @@ -285,7 +288,7 @@ export interface NonRedirectionRouteMatch extends BaseRedirectionRouteMatch { export interface RedirectionRouteMatch extends BaseRedirectionRouteMatch { originateFromRedirection: true; - redirectionOnlyQueryParams?: Route['queryParams']; + redirectionOnlyQueryParams: Route['queryParams'] | undefined; } export type RouteMatch = NonRedirectionRouteMatch | RedirectionRouteMatch; @@ -441,7 +444,8 @@ export class RouteConfigs { deepLinkProvider: definition.deepLinkProvider ?? null, pathname: definition.path, params: {}, - originateFromRedirection: wasRedirected, + originateFromRedirection: true, + redirectionOnlyQueryParams: undefined, }; } diff --git a/tensorboard/webapp/app_routing/route_config_test.ts b/tensorboard/webapp/app_routing/route_config_test.ts index 2c6f359f940..6850882b3b3 100644 --- a/tensorboard/webapp/app_routing/route_config_test.ts +++ b/tensorboard/webapp/app_routing/route_config_test.ts @@ -54,7 +54,7 @@ function buildRouteMatch(override: Partial = {}): RouteMatch { deepLinkProvider: null, originateFromRedirection: false, ...override, - }; + } as RouteMatch; } describe('route config', () => { @@ -224,6 +224,8 @@ describe('route config', () => { routeKind: RouteKind.EXPERIMENT, pathname: '/tb/bestest', params: {}, + originateFromRedirection: true, + redirectionOnlyQueryParams: undefined, }) ); }); @@ -268,6 +270,8 @@ describe('route config', () => { routeKind: RouteKind.EXPERIMENT, pathname: '/tb', params: {}, + originateFromRedirection: true, + redirectionOnlyQueryParams: undefined, }) ); }); @@ -494,6 +498,8 @@ describe('route config', () => { routeKind: RouteKind.EXPERIMENT, pathname: '/default', params: {}, + originateFromRedirection: true, + redirectionOnlyQueryParams: undefined, }) ); }); @@ -508,6 +514,7 @@ describe('route config', () => { buildRouteMatch({ pathname: '/c', originateFromRedirection: true, + redirectionOnlyQueryParams: undefined, }) ); }); diff --git a/tensorboard/webapp/experiments/store/experiments_reducers.ts b/tensorboard/webapp/experiments/store/experiments_reducers.ts index b133cd48589..3fa6933489b 100644 --- a/tensorboard/webapp/experiments/store/experiments_reducers.ts +++ b/tensorboard/webapp/experiments/store/experiments_reducers.ts @@ -19,9 +19,10 @@ import { createReducer, } from '@ngrx/store'; import {DEFAULT_EXPERIMENT_ID} from '../../app_routing/types'; +import {Experiment} from '../types'; import {ExperimentsDataState, ExperimentsState} from './experiments_types'; -const defaultExperiment = { +const defaultExperiment: Experiment = { id: DEFAULT_EXPERIMENT_ID, name: '', start_time: 0, diff --git a/tensorboard/webapp/experiments/store/testing.ts b/tensorboard/webapp/experiments/store/testing.ts index 0916337cb94..5338443cd7b 100644 --- a/tensorboard/webapp/experiments/store/testing.ts +++ b/tensorboard/webapp/experiments/store/testing.ts @@ -24,13 +24,11 @@ import { * Builds an experiment from default. Can override fields by providing * `override`. */ -export function buildExperiment(override?: Partial) { +export function buildExperiment(override?: Partial): Experiment { return { id: '1', - description: undefined, name: 'Default Experiment', start_time: 1, - tags: undefined, ...override, }; } diff --git a/tensorboard/webapp/metrics/actions/index.ts b/tensorboard/webapp/metrics/actions/index.ts index 62a06d7d1c7..64300a0ed88 100644 --- a/tensorboard/webapp/metrics/actions/index.ts +++ b/tensorboard/webapp/metrics/actions/index.ts @@ -173,7 +173,7 @@ export const timeSelectionChanged = createAction( '[Metrics] Linked Time Selection Changed', props<{ startStep: number; - endStep?: number; + endStep: number | undefined; }>() ); diff --git a/tensorboard/webapp/metrics/effects/index.ts b/tensorboard/webapp/metrics/effects/index.ts index ac8e7540dd1..f2d3dd5d21b 100644 --- a/tensorboard/webapp/metrics/effects/index.ts +++ b/tensorboard/webapp/metrics/effects/index.ts @@ -199,9 +199,13 @@ export class MetricsEffects implements OnInitEffects { */ const requests: TimeSeriesRequest[] = fetchInfos.map((fetchInfo) => { const {plugin, tag, runId, sample} = fetchInfo; - return isSingleRunPlugin(plugin) - ? {plugin, tag, sample, runId: runId!} - : {plugin, tag, sample, experimentIds}; + const partialRequest: TimeSeriesRequest = isSingleRunPlugin(plugin) + ? {plugin, tag, runId: runId!} + : {plugin, tag, experimentIds}; + if (sample !== undefined) { + partialRequest.sample = sample; + } + return partialRequest; }); // Fetch and handle responses. diff --git a/tensorboard/webapp/metrics/effects/metrics_effects_test.ts b/tensorboard/webapp/metrics/effects/metrics_effects_test.ts index 1a1890da766..fc32625adbe 100644 --- a/tensorboard/webapp/metrics/effects/metrics_effects_test.ts +++ b/tensorboard/webapp/metrics/effects/metrics_effects_test.ts @@ -36,6 +36,7 @@ import { PluginType, SingleRunPluginType, TagMetadata, + TimeSeriesRequest, TimeSeriesResponse, } from '../data_source'; import {getMetricsTagMetadataLoadState} from '../store'; @@ -328,11 +329,10 @@ describe('metrics effects', () => { } } - function buildTimeSeriesResponse() { + function buildTimeSeriesResponse(): TimeSeriesResponse { return { plugin: PluginType.SCALARS, tag: 'tagA', - sample: undefined, runToSeries: { run1: createScalarStepData(), }, @@ -377,13 +377,11 @@ describe('metrics effects', () => { plugin: PluginType.SCALARS as MultiRunPluginType, tag: 'tagA', experimentIds: ['exp1'], - sample: undefined, }, { plugin: PluginType.SCALARS as MultiRunPluginType, tag: 'tagA', experimentIds: ['exp1'], - sample: undefined, }, ], }), @@ -425,7 +423,6 @@ describe('metrics effects', () => { plugin: PluginType.SCALARS as MultiRunPluginType, tag: 'tagA', experimentIds: ['exp1'], - sample: undefined, }, ], }), @@ -594,11 +591,10 @@ describe('metrics effects', () => { }) ); - const expectedRequest = { + const expectedRequest: TimeSeriesRequest = { plugin: PluginType.SCALARS as MultiRunPluginType, tag: 'tagA', experimentIds: ['exp1'], - sample: undefined, }; expect(fetchTimeSeriesSpy.calls.count()).toBe(1); expect(fetchTimeSeriesSpy).toHaveBeenCalledWith([expectedRequest]); @@ -693,12 +689,11 @@ describe('metrics effects', () => { }) ); - const expectedRequests = [ + const expectedRequests: TimeSeriesRequest[] = [ { plugin: PluginType.SCALARS as MultiRunPluginType, tag: 'tagA', experimentIds: ['exp1'], - sample: undefined, }, { plugin: PluginType.IMAGES as SingleRunPluginType, diff --git a/tensorboard/webapp/metrics/store/metrics_reducers_test.ts b/tensorboard/webapp/metrics/store/metrics_reducers_test.ts index 315c51862c9..a23aaf13d43 100644 --- a/tensorboard/webapp/metrics/store/metrics_reducers_test.ts +++ b/tensorboard/webapp/metrics/store/metrics_reducers_test.ts @@ -2018,7 +2018,7 @@ describe('metrics reducers', () => { const after = reducers( before, - actions.timeSelectionChanged({startStep: 2}) + actions.timeSelectionChanged({startStep: 2, endStep: undefined}) ); expect(after.selectedTime).toEqual({ @@ -2058,9 +2058,7 @@ describe('metrics reducers', () => { const after = reducers( before, - actions.timeSelectionChanged({ - startStep: 2, - }) + actions.timeSelectionChanged({startStep: 2, endStep: undefined}) ); expect(after.selectedTime).toEqual({ @@ -2077,9 +2075,7 @@ describe('metrics reducers', () => { const nextState = reducers( beforeState, - actions.timeSelectionChanged({ - startStep: 2, - }) + actions.timeSelectionChanged({startStep: 2, endStep: undefined}) ); expect(nextState.selectTimeEnabled).toBe(true); @@ -2116,9 +2112,7 @@ describe('metrics reducers', () => { const nextState = reducers( beforeState, - actions.timeSelectionChanged({ - startStep: 150, - }) + actions.timeSelectionChanged({startStep: 150, endStep: undefined}) ); expect(nextState.selectedTime).toEqual({ diff --git a/tensorboard/webapp/metrics/views/card_renderer/card_lazy_loader.ts b/tensorboard/webapp/metrics/views/card_renderer/card_lazy_loader.ts index 153d560084f..387c385a494 100644 --- a/tensorboard/webapp/metrics/views/card_renderer/card_lazy_loader.ts +++ b/tensorboard/webapp/metrics/views/card_renderer/card_lazy_loader.ts @@ -57,9 +57,17 @@ export class CardObserver { return; } this.intersectionCallback = intersectionCallback; + + const init: IntersectionObserverInit = { + threshold: 0, + root: this.root ?? null, + }; + if (this.buffer) { + init.rootMargin = this.buffer; + } this.intersectionObserver = new IntersectionObserver( this.onCardIntersection.bind(this), - {threshold: 0, root: this.root, rootMargin: this.buffer} + init ); } diff --git a/tensorboard/webapp/persistent_settings/_data_source/persistent_settings_data_source.ts b/tensorboard/webapp/persistent_settings/_data_source/persistent_settings_data_source.ts index f1e5c1aadb6..73628534be0 100644 --- a/tensorboard/webapp/persistent_settings/_data_source/persistent_settings_data_source.ts +++ b/tensorboard/webapp/persistent_settings/_data_source/persistent_settings_data_source.ts @@ -44,22 +44,51 @@ export class OSSSettingsConverter extends SettingsConverter< BackendSettings > { uiToBackend(settings: PersistableSettings): BackendSettings { - const serializableSettings: BackendSettings = { - ignoreOutliers: settings.ignoreOutliers, - scalarSmoothing: settings.scalarSmoothing, + const serializableSettings: BackendSettings = {}; + + if (settings.ignoreOutliers !== undefined) { + serializableSettings.ignoreOutliers = settings.ignoreOutliers; + } + if (settings.scalarSmoothing !== undefined) { + serializableSettings.scalarSmoothing = settings.scalarSmoothing; + } + if (settings.tooltipSortString !== undefined) { // TooltipSort is a string enum and has string values; no need to // serialize it differently to account for their unintended changes. - tooltipSort: settings.tooltipSortString, - autoReload: settings.autoReload, - autoReloadPeriodInMs: settings.autoReloadPeriodInMs, - paginationSize: settings.pageSize, - theme: settings.themeOverride, - notificationLastReadTimeInMs: settings.notificationLastReadTimeInMs, - sideBarWidthInPercent: settings.sideBarWidthInPercent, - timeSeriesPromotionDismissed: settings.timeSeriesPromotionDismissed, - timeSeriesSettingsPaneOpened: settings.timeSeriesSettingsPaneOpened, - timeSeriesCardMinWidth: settings.timeSeriesCardMinWidth, - }; + serializableSettings.tooltipSort = settings.tooltipSortString; + } + if (settings.autoReload !== undefined) { + serializableSettings.autoReload = settings.autoReload; + } + if (settings.autoReloadPeriodInMs !== undefined) { + serializableSettings.autoReloadPeriodInMs = settings.autoReloadPeriodInMs; + } + if (settings.pageSize !== undefined) { + serializableSettings.paginationSize = settings.pageSize; + } + if (settings.themeOverride !== undefined) { + serializableSettings.theme = settings.themeOverride; + } + if (settings.notificationLastReadTimeInMs !== undefined) { + serializableSettings.notificationLastReadTimeInMs = + settings.notificationLastReadTimeInMs; + } + if (settings.sideBarWidthInPercent !== undefined) { + serializableSettings.sideBarWidthInPercent = + settings.sideBarWidthInPercent; + } + if (settings.timeSeriesPromotionDismissed !== undefined) { + serializableSettings.timeSeriesPromotionDismissed = + settings.timeSeriesPromotionDismissed; + } + if (settings.timeSeriesSettingsPaneOpened !== undefined) { + serializableSettings.timeSeriesSettingsPaneOpened = + settings.timeSeriesSettingsPaneOpened; + } + if (settings.timeSeriesCardMinWidth !== undefined) { + serializableSettings.timeSeriesCardMinWidth = + settings.timeSeriesCardMinWidth; + } return serializableSettings; } diff --git a/tensorboard/webapp/plugins/npmi/actions/npmi_actions.ts b/tensorboard/webapp/plugins/npmi/actions/npmi_actions.ts index 4e0f1669b7f..314747010c7 100644 --- a/tensorboard/webapp/plugins/npmi/actions/npmi_actions.ts +++ b/tensorboard/webapp/plugins/npmi/actions/npmi_actions.ts @@ -33,7 +33,7 @@ export const npmiPluginDataLoaded = createAction( props<{ annotationData: AnnotationDataListing; metrics: MetricListing; - embeddingDataSet?: EmbeddingDataSet; + embeddingDataSet: EmbeddingDataSet | undefined; }>() ); diff --git a/tensorboard/webapp/plugins/npmi/data_source/npmi_data_source.ts b/tensorboard/webapp/plugins/npmi/data_source/npmi_data_source.ts index 9d430d92b0a..b7e3bbf440c 100644 --- a/tensorboard/webapp/plugins/npmi/data_source/npmi_data_source.ts +++ b/tensorboard/webapp/plugins/npmi/data_source/npmi_data_source.ts @@ -32,7 +32,7 @@ export abstract class NpmiDataSource { abstract fetchData(experimentIds: string[]): Observable<{ annotationData: AnnotationDataListing; metrics: MetricListing; - embeddingDataSet?: EmbeddingDataSet; + embeddingDataSet: EmbeddingDataSet | undefined; }>; } diff --git a/tensorboard/webapp/plugins/npmi/store/npmi_reducers.ts b/tensorboard/webapp/plugins/npmi/store/npmi_reducers.ts index af2f82b44d8..210a96df7e4 100644 --- a/tensorboard/webapp/plugins/npmi/store/npmi_reducers.ts +++ b/tensorboard/webapp/plugins/npmi/store/npmi_reducers.ts @@ -32,6 +32,7 @@ const initialState: NpmiState = { lastLoadedTimeInMs: null, }, annotationData: {}, + embeddingDataSet: undefined, runToMetrics: {}, selectedAnnotations: [], flaggedAnnotations: [], diff --git a/tensorboard/webapp/plugins/npmi/store/npmi_types.ts b/tensorboard/webapp/plugins/npmi/store/npmi_types.ts index 8fa71ef714e..4a702e50b72 100644 --- a/tensorboard/webapp/plugins/npmi/store/npmi_types.ts +++ b/tensorboard/webapp/plugins/npmi/store/npmi_types.ts @@ -87,7 +87,7 @@ export interface NpmiState { pluginDataLoaded: LoadState; annotationData: AnnotationDataListing; runToMetrics: MetricListing; - embeddingDataSet?: EmbeddingDataSet; + embeddingDataSet: EmbeddingDataSet | undefined; // based on user interaction selectedAnnotations: Annotation[]; diff --git a/tensorboard/webapp/plugins/npmi/testing/index.ts b/tensorboard/webapp/plugins/npmi/testing/index.ts index f51b8c4f313..2b396cf6834 100644 --- a/tensorboard/webapp/plugins/npmi/testing/index.ts +++ b/tensorboard/webapp/plugins/npmi/testing/index.ts @@ -29,6 +29,7 @@ export function createNpmiState(override?: Partial): NpmiState { lastLoadedTimeInMs: null, }, annotationData: {}, + embeddingDataSet: undefined, runToMetrics: {}, selectedAnnotations: [], flaggedAnnotations: [], diff --git a/tensorboard/webapp/runs/views/runs_table/runs_table_test.ts b/tensorboard/webapp/runs/views/runs_table/runs_table_test.ts index 7193c4c843e..4baa94d18be 100644 --- a/tensorboard/webapp/runs/views/runs_table/runs_table_test.ts +++ b/tensorboard/webapp/runs/views/runs_table/runs_table_test.ts @@ -167,7 +167,9 @@ describe('runs_table', () => { if (columns) { fixture.componentInstance.columns = columns; } - fixture.componentInstance.usePagination = usePagination; + if (usePagination !== undefined) { + fixture.componentInstance.usePagination = usePagination; + } fixture.detectChanges(); return fixture; diff --git a/tensorboard/webapp/settings/_redux/settings_reducers.ts b/tensorboard/webapp/settings/_redux/settings_reducers.ts index ed7c32ea952..2151602d305 100644 --- a/tensorboard/webapp/settings/_redux/settings_reducers.ts +++ b/tensorboard/webapp/settings/_redux/settings_reducers.ts @@ -89,7 +89,7 @@ const reducer = createReducer( Number.isFinite(partialSettings.pageSize) && partialSettings.pageSize! > 0 ) { - nextSettings.pageSize = partialSettings.pageSize; + nextSettings.pageSize = Number(partialSettings.pageSize); } if (typeof partialSettings.autoReload === 'boolean') { @@ -100,7 +100,9 @@ const reducer = createReducer( Number.isFinite(partialSettings.autoReloadPeriodInMs) && partialSettings.autoReloadPeriodInMs! > MIN_RELOAD_PERIOD_IN_MS ) { - nextSettings.reloadPeriodInMs = partialSettings.autoReloadPeriodInMs; + nextSettings.reloadPeriodInMs = Number( + partialSettings.autoReloadPeriodInMs + ); } return { diff --git a/tensorboard/webapp/webapp_data_source/tb_http_client.ts b/tensorboard/webapp/webapp_data_source/tb_http_client.ts index b03bf689d5a..c0969f84a92 100644 --- a/tensorboard/webapp/webapp_data_source/tb_http_client.ts +++ b/tensorboard/webapp/webapp_data_source/tb_http_client.ts @@ -84,7 +84,7 @@ export class TBHttpClient implements TBHttpClientInterface { path: string, // Angular's HttpClient is typed exactly this way. body: any | null, - options: PostOptions = {} + options: PostOptions | undefined = {} ): Observable { options = withXsrfHeader(options); return this.store.select(getIsFeatureFlagsLoaded).pipe( @@ -99,7 +99,7 @@ export class TBHttpClient implements TBHttpClientInterface { // See b/72932164. if (isInColab) { return this.http.get(resolvedPath, { - headers: options.headers, + headers: options.headers ?? {}, params: convertFormDataToObject(body), }); } else { diff --git a/tensorboard/webapp/widgets/intersection_observer/intersection_observer_directive.ts b/tensorboard/webapp/widgets/intersection_observer/intersection_observer_directive.ts index 6257e4cf5c8..1028f5a7e61 100644 --- a/tensorboard/webapp/widgets/intersection_observer/intersection_observer_directive.ts +++ b/tensorboard/webapp/widgets/intersection_observer/intersection_observer_directive.ts @@ -51,7 +51,7 @@ export class IntersectionObserverDirective implements OnInit, OnDestroy { root: this.cdkScrollable ? this.cdkScrollable.getElementRef().nativeElement : null, - rootMargin: this.intersectionObserverMargin, + rootMargin: this.intersectionObserverMargin ?? '', } ); intersectionObserver.observe(this.ref.nativeElement); diff --git a/tensorboard/webapp/widgets/line_chart_v2/sub_view/line_chart_interactive_utils_test.ts b/tensorboard/webapp/widgets/line_chart_v2/sub_view/line_chart_interactive_utils_test.ts index 8fdcb90bcbe..646b39480ae 100644 --- a/tensorboard/webapp/widgets/line_chart_v2/sub_view/line_chart_interactive_utils_test.ts +++ b/tensorboard/webapp/widgets/line_chart_v2/sub_view/line_chart_interactive_utils_test.ts @@ -103,12 +103,17 @@ describe('line_chart_v2/sub_view/interactive_utils test', () => { wheelOption: Partial = {}, mouseOption: Partial<{offsetX: number; offsetY: number}> = {} ): WheelEvent { - const event = new WheelEvent('wheel', { + const wheelEventInit: WheelEventInit = { deltaMode: WheelEvent.DOM_DELTA_LINE, ...wheelOption, - clientX: mouseOption.offsetX, - clientY: mouseOption.offsetY, - }); + }; + if (mouseOption.offsetX !== undefined) { + wheelEventInit.clientX = mouseOption.offsetX; + } + if (mouseOption.offsetY !== undefined) { + wheelEventInit.clientY = mouseOption.offsetY; + } + const event = new WheelEvent('wheel', wheelEventInit); return event; } diff --git a/tsconfig.json b/tsconfig.json index 95a20080a43..6fdf1cac80e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,6 +2,7 @@ "compilerOptions": { "downlevelIteration": true, "emitDecoratorMetadata": true, + "exactOptionalPropertyTypes": true, "experimentalDecorators": true, "importHelpers": true, "inlineSourceMap": true,