From c757569697315f85f1c4d5f5b39c17070c3b37e4 Mon Sep 17 00:00:00 2001 From: Eldar Iusupzhanov Date: Wed, 5 Aug 2026 14:46:04 +0600 Subject: [PATCH 1/3] fix --- .../data_controller/data_helper_mixin.ts | 140 ++++++++++-------- 1 file changed, 75 insertions(+), 65 deletions(-) diff --git a/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_helper_mixin.ts b/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_helper_mixin.ts index 550878ac2880..0135e094dffc 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_helper_mixin.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_helper_mixin.ts @@ -1,13 +1,3 @@ -// TODO: fix the rules disabled below -/* eslint-disable @stylistic/max-len */ -/* eslint-disable @typescript-eslint/explicit-function-return-type */ -/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ -/* eslint-disable @typescript-eslint/init-declarations */ -/* eslint-disable @typescript-eslint/no-explicit-any */ -/* eslint-disable @typescript-eslint/no-shadow */ -/* eslint-disable @typescript-eslint/no-unsafe-return */ -/* eslint-disable @typescript-eslint/no-unused-expressions */ -/* eslint-disable no-param-reassign */ import { DataSource } from '@js/common/data/data_source/data_source'; import { normalizeDataSourceOptions } from '@js/common/data/data_source/utils'; import { extend } from '@js/core/utils/extend'; @@ -24,25 +14,31 @@ const DATA_SOURCE_FROM_URL_LOAD_MODE_METHOD = '_dataSourceFromUrlLoadMode'; const SPECIFIC_DATA_SOURCE_OPTION = '_getSpecificDataSourceOption'; const NORMALIZE_DATA_SOURCE = '_normalizeDataSource'; +type ProxiedDataSourceHandler = (...args: unknown[]) => void; + // TODO Get rid of this mixin -export const DataHelperMixin = >(Base: T) => class DataHelperMixin extends Base { - public _dataSource: any; +// eslint-disable-next-line +export const DataHelperMixin = >(Base: T) => class extends Base { + public _dataSource?: unknown; + + protected _dataController?: DataController; - protected _dataController: any; + protected readyWatcher?: (isLoading: boolean) => void; - protected readyWatcher: any; + // Optional hook implemented by Widget-based consumers (see Widget#_ready). + protected _ready?: (value?: boolean) => void; - private _proxiedDataSourceChangedHandler: any; + private _proxiedDataSourceChangedHandler?: ProxiedDataSourceHandler; - private _proxiedDataSourceLoadErrorHandler: any; + private _proxiedDataSourceLoadErrorHandler?: ProxiedDataSourceHandler; - private _proxiedDataSourceLoadingChangedHandler: any; + private _proxiedDataSourceLoadingChangedHandler?: ProxiedDataSourceHandler; - protected _isSharedDataSource: any; + protected _isSharedDataSource?: boolean; - private readonly _dataSourceType: any; + private readonly _dataSourceType?: () => typeof DataSource; - public postCtor() { + public postCtor(): void { this.on('disposing', () => { this._disposeDataSource(); }); @@ -51,19 +47,17 @@ export const DataHelperMixin = >(Base: T) => cl /** * @extended: state_storing, virtual_scrolling */ - protected _refreshDataSource() { + protected _refreshDataSource(): void { this._initDataSource(); this._loadDataSource(); } - protected _initDataSource() { + protected _initDataSource(): void { let dataSourceOptions = SPECIFIC_DATA_SOURCE_OPTION in this - ? (this[SPECIFIC_DATA_SOURCE_OPTION] as any)() + // @ts-expect-error dynamic mixin method + ? this[SPECIFIC_DATA_SOURCE_OPTION]() : this.option('dataSource'); - let widgetDataSourceOptions; - let dataSourceType; - this._disposeDataSource(); if (dataSourceOptions) { @@ -71,22 +65,29 @@ export const DataHelperMixin = >(Base: T) => cl this._isSharedDataSource = true; this._dataSource = dataSourceOptions; } else { - widgetDataSourceOptions = DATA_SOURCE_OPTIONS_METHOD in this - ? (this[DATA_SOURCE_OPTIONS_METHOD] as any)() + const widgetDataSourceOptions = DATA_SOURCE_OPTIONS_METHOD in this + // @ts-expect-error dynamic mixin method + ? this[DATA_SOURCE_OPTIONS_METHOD]() : {}; - dataSourceType = this._dataSourceType ? this._dataSourceType() : DataSource; + const DataSourceType = this._dataSourceType + ? this._dataSourceType() + : DataSource; dataSourceOptions = normalizeDataSourceOptions(dataSourceOptions, { - fromUrlLoadMode: (DATA_SOURCE_FROM_URL_LOAD_MODE_METHOD in this) && (this[DATA_SOURCE_FROM_URL_LOAD_MODE_METHOD] as any)(), + fromUrlLoadMode: (DATA_SOURCE_FROM_URL_LOAD_MODE_METHOD in this) + // @ts-expect-error dynamic mixin method + && this[DATA_SOURCE_FROM_URL_LOAD_MODE_METHOD](), }); - // eslint-disable-next-line new-cap - this._dataSource = new dataSourceType(extend(true, {}, widgetDataSourceOptions, dataSourceOptions)); + this._dataSource = new DataSourceType( + extend(true, {}, widgetDataSourceOptions, dataSourceOptions), + ); } if (NORMALIZE_DATA_SOURCE in this) { - this._dataSource = (this[NORMALIZE_DATA_SOURCE] as any)(this._dataSource); + // @ts-expect-error dynamic mixin method + this._dataSource = this[NORMALIZE_DATA_SOURCE](this._dataSource); } this._addDataSourceHandlers(); @@ -94,7 +95,7 @@ export const DataHelperMixin = >(Base: T) => cl } } - private _initDataController() { + private _initDataController(): void { const dataController = this.option?.('_dataController'); const dataSource = this._dataSource; @@ -105,7 +106,7 @@ export const DataHelperMixin = >(Base: T) => cl } } - private _addDataSourceHandlers() { + private _addDataSourceHandlers(): void { if (DATA_SOURCE_CHANGED_METHOD in this) { this._addDataSourceChangeHandler(); } @@ -121,68 +122,77 @@ export const DataHelperMixin = >(Base: T) => cl this._addReadyWatcher(); } - private _addReadyWatcher() { - this.readyWatcher = function (isLoading) { - this._ready && this._ready(!isLoading); - }.bind(this); + private _addReadyWatcher(): void { + this.readyWatcher = (isLoading: boolean): void => { + this._ready?.(!isLoading); + }; + // @ts-expect-error _dataSource is loosely typed this._dataSource.on('loadingChanged', this.readyWatcher); } - private _addDataSourceChangeHandler() { + private _addDataSourceChangeHandler(): void { const dataSource = this._dataSource; - this._proxiedDataSourceChangedHandler = function (e) { + this._proxiedDataSourceChangedHandler = function dataSourceChangedHandler(e): void { + // @ts-expect-error _dataSource is loosely typed this[DATA_SOURCE_CHANGED_METHOD](dataSource.items(), e); }.bind(this); + // @ts-expect-error _dataSource is loosely typed dataSource.on('changed', this._proxiedDataSourceChangedHandler); } - private _addDataSourceLoadErrorHandler() { + private _addDataSourceLoadErrorHandler(): void { this._proxiedDataSourceLoadErrorHandler = this[DATA_SOURCE_LOAD_ERROR_METHOD].bind(this); + // @ts-expect-error _dataSource is loosely typed this._dataSource.on('loadError', this._proxiedDataSourceLoadErrorHandler); } - private _addDataSourceLoadingChangedHandler() { - this._proxiedDataSourceLoadingChangedHandler = this[DATA_SOURCE_LOADING_CHANGED_METHOD].bind(this); + private _addDataSourceLoadingChangedHandler(): void { + this._proxiedDataSourceLoadingChangedHandler = this[DATA_SOURCE_LOADING_CHANGED_METHOD] + .bind(this); + // @ts-expect-error _dataSource is loosely typed this._dataSource.on('loadingChanged', this._proxiedDataSourceLoadingChangedHandler); } - protected _loadDataSource() { + protected _loadDataSource(): void { const dataSource = this._dataSource; if (dataSource) { + // @ts-expect-error _dataSource is loosely typed if (dataSource.isLoaded()) { - this._proxiedDataSourceChangedHandler && this._proxiedDataSourceChangedHandler(); + if (this._proxiedDataSourceChangedHandler) { + this._proxiedDataSourceChangedHandler(); + } } else { + // @ts-expect-error _dataSource is loosely typed dataSource.load(); } } } - private _loadSingle(key, value) { - key = key === 'this' ? this._dataSource.key() || 'this' : key; - return this._dataSource.loadSingle(key, value); - } - - private _isLastPage() { - return !this._dataSource || this._dataSource.isLastPage() || !this._dataSource._pageSize; - } - - private _isDataSourceLoading() { - return this._dataSource && this._dataSource.isLoading(); - } - - protected _disposeDataSource() { + protected _disposeDataSource(): void { if (this._dataSource) { if (this._isSharedDataSource) { delete this._isSharedDataSource; - this._proxiedDataSourceChangedHandler && this._dataSource.off('changed', this._proxiedDataSourceChangedHandler); - this._proxiedDataSourceLoadErrorHandler && this._dataSource.off('loadError', this._proxiedDataSourceLoadErrorHandler); - this._proxiedDataSourceLoadingChangedHandler && this._dataSource.off('loadingChanged', this._proxiedDataSourceLoadingChangedHandler); + if (this._proxiedDataSourceChangedHandler) { + // @ts-expect-error _dataSource is loosely typed + this._dataSource.off('changed', this._proxiedDataSourceChangedHandler); + } + if (this._proxiedDataSourceLoadErrorHandler) { + // @ts-expect-error _dataSource is loosely typed + this._dataSource.off('loadError', this._proxiedDataSourceLoadErrorHandler); + } + if (this._proxiedDataSourceLoadingChangedHandler) { + // @ts-expect-error _dataSource is loosely typed + this._dataSource.off('loadingChanged', this._proxiedDataSourceLoadingChangedHandler); + } + // @ts-expect-error _dataSource is loosely typed if (this._dataSource._eventsStrategy) { + // @ts-expect-error _dataSource is loosely typed this._dataSource._eventsStrategy.off('loadingChanged', this.readyWatcher); } } else { + // @ts-expect-error _dataSource is loosely typed this._dataSource.dispose(); } @@ -194,7 +204,7 @@ export const DataHelperMixin = >(Base: T) => cl } } - protected getDataSource() { - return this._dataSource || null; + protected getDataSource(): unknown { + return this._dataSource ?? null; } }; From 046412ec668d5fc8fa70e9c2402cfc0d422fae5b Mon Sep 17 00:00:00 2001 From: Eldar Iusupzhanov Date: Wed, 5 Aug 2026 18:46:29 +0600 Subject: [PATCH 2/3] apply review --- .../data_controller/data_controller.ts | 2 +- .../data_controller/data_helper_mixin.ts | 25 ++++++------------- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_controller.ts b/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_controller.ts index b400ce989891..9471efa6fc35 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_controller.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_controller.ts @@ -218,7 +218,7 @@ export class DataController extends DataHelperMixin(modules.Controller) { this.dataErrorOccurred.add((error) => this.executeAction('onDataErrorOccurred', { error })); this._refreshDataSource(); - this.postCtor(); + this.postInit(); } /** diff --git a/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_helper_mixin.ts b/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_helper_mixin.ts index 0135e094dffc..7044233716ce 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_helper_mixin.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_helper_mixin.ts @@ -17,9 +17,11 @@ const NORMALIZE_DATA_SOURCE = '_normalizeDataSource'; type ProxiedDataSourceHandler = (...args: unknown[]) => void; // TODO Get rid of this mixin -// eslint-disable-next-line +// eslint-disable-next-line @stylistic/max-len +// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/explicit-function-return-type export const DataHelperMixin = >(Base: T) => class extends Base { - public _dataSource?: unknown; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + public _dataSource?: any; protected _dataController?: DataController; @@ -38,7 +40,7 @@ export const DataHelperMixin = >(Base: T) => cl private readonly _dataSourceType?: () => typeof DataSource; - public postCtor(): void { + public postInit(): void { this.on('disposing', () => { this._disposeDataSource(); }); @@ -126,43 +128,36 @@ export const DataHelperMixin = >(Base: T) => cl this.readyWatcher = (isLoading: boolean): void => { this._ready?.(!isLoading); }; - // @ts-expect-error _dataSource is loosely typed this._dataSource.on('loadingChanged', this.readyWatcher); } private _addDataSourceChangeHandler(): void { const dataSource = this._dataSource; - this._proxiedDataSourceChangedHandler = function dataSourceChangedHandler(e): void { - // @ts-expect-error _dataSource is loosely typed + this._proxiedDataSourceChangedHandler = (e): void => { this[DATA_SOURCE_CHANGED_METHOD](dataSource.items(), e); - }.bind(this); - // @ts-expect-error _dataSource is loosely typed + }; dataSource.on('changed', this._proxiedDataSourceChangedHandler); } private _addDataSourceLoadErrorHandler(): void { this._proxiedDataSourceLoadErrorHandler = this[DATA_SOURCE_LOAD_ERROR_METHOD].bind(this); - // @ts-expect-error _dataSource is loosely typed this._dataSource.on('loadError', this._proxiedDataSourceLoadErrorHandler); } private _addDataSourceLoadingChangedHandler(): void { this._proxiedDataSourceLoadingChangedHandler = this[DATA_SOURCE_LOADING_CHANGED_METHOD] .bind(this); - // @ts-expect-error _dataSource is loosely typed this._dataSource.on('loadingChanged', this._proxiedDataSourceLoadingChangedHandler); } protected _loadDataSource(): void { const dataSource = this._dataSource; if (dataSource) { - // @ts-expect-error _dataSource is loosely typed if (dataSource.isLoaded()) { if (this._proxiedDataSourceChangedHandler) { this._proxiedDataSourceChangedHandler(); } } else { - // @ts-expect-error _dataSource is loosely typed dataSource.load(); } } @@ -174,25 +169,19 @@ export const DataHelperMixin = >(Base: T) => cl delete this._isSharedDataSource; if (this._proxiedDataSourceChangedHandler) { - // @ts-expect-error _dataSource is loosely typed this._dataSource.off('changed', this._proxiedDataSourceChangedHandler); } if (this._proxiedDataSourceLoadErrorHandler) { - // @ts-expect-error _dataSource is loosely typed this._dataSource.off('loadError', this._proxiedDataSourceLoadErrorHandler); } if (this._proxiedDataSourceLoadingChangedHandler) { - // @ts-expect-error _dataSource is loosely typed this._dataSource.off('loadingChanged', this._proxiedDataSourceLoadingChangedHandler); } - // @ts-expect-error _dataSource is loosely typed if (this._dataSource._eventsStrategy) { - // @ts-expect-error _dataSource is loosely typed this._dataSource._eventsStrategy.off('loadingChanged', this.readyWatcher); } } else { - // @ts-expect-error _dataSource is loosely typed this._dataSource.dispose(); } From 447f792786992d8300ff542245bc61ddee5853bb Mon Sep 17 00:00:00 2001 From: Eldar Iusupzhanov Date: Wed, 5 Aug 2026 19:10:32 +0600 Subject: [PATCH 3/3] fix --- .../grids/grid_core/data_controller/data_helper_mixin.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_helper_mixin.ts b/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_helper_mixin.ts index 7044233716ce..c8fc65d55cb1 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_helper_mixin.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_helper_mixin.ts @@ -193,7 +193,8 @@ export const DataHelperMixin = >(Base: T) => cl } } - protected getDataSource(): unknown { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + protected getDataSource(): any | null { return this._dataSource ?? null; } };