From 54b043ef494680bd2f5d96b31d1b89ebcf009d4e Mon Sep 17 00:00:00 2001 From: Maksim Zakharov <251575087+bit-byte0@users.noreply.github.com> Date: Wed, 2 Sep 2026 12:10:50 +0400 Subject: [PATCH 1/4] refactor(dataSourceAdapter): type public methods and props --- .../grids/data_grid/focus/m_focus.ts | 12 ++++------ .../extenders/grouping_data_controller.ts | 6 ++--- .../grids/data_grid/grouping/m_grouping.ts | 10 ++++---- .../extenders/summary_data_controller.ts | 7 +++--- .../grids/data_grid/summary/m_summary.ts | 4 +++- .../data_controller/data_controller.ts | 14 +++++------ .../grids/grid_core/data_controller/types.ts | 7 ------ .../m_data_source_adapter.ts | 24 ++++++++++++------- .../virtual_scrolling_data_controller.ts | 5 +--- .../grid_core/virtual_scrolling/index.ts | 7 +++++- .../virtual_scrolling/m_virtual_scrolling.ts | 10 ++++---- .../m_virtual_scrolling_core.ts | 2 +- .../data_controller/m_data_controller.ts | 1 - .../m_data_source_adapter.ts | 2 +- .../js/__internal/grids/tree_list/m_focus.ts | 2 -- .../grids/tree_list/m_virtual_scrolling.ts | 6 +++-- 16 files changed, 60 insertions(+), 59 deletions(-) diff --git a/packages/devextreme/js/__internal/grids/data_grid/focus/m_focus.ts b/packages/devextreme/js/__internal/grids/data_grid/focus/m_focus.ts index 3aa4315f72de..55b785a11388 100644 --- a/packages/devextreme/js/__internal/grids/data_grid/focus/m_focus.ts +++ b/packages/devextreme/js/__internal/grids/data_grid/focus/m_focus.ts @@ -1,12 +1,11 @@ import { equalByValue } from '@js/core/utils/common'; import { compileGetter } from '@js/core/utils/data'; import { Deferred } from '@js/core/utils/deferred'; -import { isDefined } from '@js/core/utils/type'; import type { DataController } from '@ts/grids/grid_core/data_controller/data_controller'; import { focusModule } from '@ts/grids/grid_core/focus/m_focus'; import type { ModuleType } from '@ts/grids/grid_core/m_types'; -import type { GroupingDataControllerExtension } from '../grouping/m_grouping'; +import type { GroupingDataControllerExtension, GroupingDataSourceAdapter } from '../grouping/m_grouping'; import gridCore from '../m_core'; import { createGroupFilter } from '../m_utils'; @@ -25,6 +24,8 @@ DataController & GroupingDataControllerExtension>; const data = (Base: DataControllerBase) => class FocusDataControllerExtender extends focusModule.extenders.controllers.data(Base) { + public declare _dataSource?: GroupingDataSourceAdapter | null; + private changeRowExpand(path, isRowClick) { // @ts-expect-error if (this.option('focusedRowEnabled') && Array.isArray(path) && this.isRowExpanded(path)) { @@ -100,7 +101,6 @@ const data = (Base: DataControllerBase) => class FocusDataControllerExtender ext const group = dataSource.group(); - // @ts-expect-error badly typed DataSourceAdapter if (!dataSource._grouping._updatePagingOptions) { this._calculateGlobalRowIndexByFlatData(key, null, true) .done(deferred.resolve) @@ -112,15 +112,13 @@ const data = (Base: DataControllerBase) => class FocusDataControllerExtender ext filter: this._concatWithCombinedFilter(filter), group, }).done((data) => { - // @ts-expect-error badly typed DataSourceAdapter - const hasData = isDefined(data) && data.length > 0; + const hasData = Array.isArray(data) && data.length > 0; if (this._dataSource !== dataSource || !hasData) { return deferred.resolve(-1).promise(); } - // @ts-expect-error badly typed DataSourceAdapter - const groupPath = this._getGroupPath(data, group.length); + const groupPath = this._getGroupPath(data, gridCore.normalizeSortingInfo(group).length); this._expandGroupByPath(this, groupPath, 0).done(() => { this._calculateExpandedRowGlobalIndex(deferred, key, groupPath, group, dataSource); diff --git a/packages/devextreme/js/__internal/grids/data_grid/grouping/extenders/grouping_data_controller.ts b/packages/devextreme/js/__internal/grids/data_grid/grouping/extenders/grouping_data_controller.ts index 916507cb79dc..440fb56af6d1 100644 --- a/packages/devextreme/js/__internal/grids/data_grid/grouping/extenders/grouping_data_controller.ts +++ b/packages/devextreme/js/__internal/grids/data_grid/grouping/extenders/grouping_data_controller.ts @@ -11,6 +11,7 @@ import type { RowKey, } from '@ts/grids/grid_core/m_types'; +import type { GroupingDataSourceAdapter } from '../m_grouping'; import type { ChangeRowExpandArgs, GroupItem, ProcessGroupItemsOptions, } from '../types'; @@ -21,6 +22,8 @@ import { export const groupingDataControllerExtender = ( Base: ModuleType, ): ModuleType => class GroupingDataControllerExtender extends Base { + public declare _dataSource?: GroupingDataSourceAdapter | null; + public init(): void { super.init(); @@ -148,7 +151,6 @@ export const groupingDataControllerExtender = ( private collapseAll(groupIndex: number): void { const dataSource = this._dataSource; - // @ts-expect-error badly typed DataSourceAdapter if (dataSource?.collapseAll(groupIndex)) { dataSource?.pageIndex(0); dataSource?.reload(); @@ -157,7 +159,6 @@ export const groupingDataControllerExtender = ( private expandAll(groupIndex: number): void { const dataSource = this._dataSource; - // @ts-expect-error badly typed DataSourceAdapter if (dataSource?.expandAll(groupIndex)) { dataSource?.pageIndex(0); dataSource?.reload(); @@ -201,7 +202,6 @@ export const groupingDataControllerExtender = ( } private isRowExpanded(key: RowKey): boolean { - // @ts-expect-error badly typed DataSourceAdapter return !!this._dataSource?.isRowExpanded(key); } diff --git a/packages/devextreme/js/__internal/grids/data_grid/grouping/m_grouping.ts b/packages/devextreme/js/__internal/grids/data_grid/grouping/m_grouping.ts index 815fc4e1ed7e..608c733636ba 100644 --- a/packages/devextreme/js/__internal/grids/data_grid/grouping/m_grouping.ts +++ b/packages/devextreme/js/__internal/grids/data_grid/grouping/m_grouping.ts @@ -34,8 +34,10 @@ export interface GroupingDataControllerExtension { changeRowExpand(key, isRowClick?): any; } +export type GroupingDataSourceAdapter = InstanceType>; + const dataSourceAdapterExtender = (Base: ModuleType) => class GroupingDataSourceAdapterExtender extends Base { - private _grouping: any; + public _grouping: any; public init() { super.init.apply(this, arguments as any); @@ -76,16 +78,16 @@ const dataSourceAdapterExtender = (Base: ModuleType) => class return this._grouping.isGroupItemCountable(item); } - private isRowExpanded(key) { + public isRowExpanded(key) { const groupInfo = this._grouping.findGroupInfo(key); return groupInfo ? groupInfo.isExpanded : !this._grouping.allowCollapseAll(); } - private collapseAll(groupIndex) { + public collapseAll(groupIndex) { return this._collapseExpandAll(groupIndex, false); } - private expandAll(groupIndex) { + public expandAll(groupIndex) { return this._collapseExpandAll(groupIndex, true); } diff --git a/packages/devextreme/js/__internal/grids/data_grid/summary/extenders/summary_data_controller.ts b/packages/devextreme/js/__internal/grids/data_grid/summary/extenders/summary_data_controller.ts index 8cf597ad96f3..a32233d8861f 100644 --- a/packages/devextreme/js/__internal/grids/data_grid/summary/extenders/summary_data_controller.ts +++ b/packages/devextreme/js/__internal/grids/data_grid/summary/extenders/summary_data_controller.ts @@ -15,6 +15,7 @@ import { isSameContinuationState } from '../../grouping/utils'; import gridCore from '../../m_core'; import { isDataColumn } from '../../m_utils'; import { DATAGRID_GROUP_FOOTER_ROW_TYPE, DATAGRID_TOTAL_FOOTER_ROW_TYPE } from '../const'; +import type { SummaryDataSourceAdapter } from '../m_summary'; import type { CalculateSummaryCellsArgs, ColumnMap, FooterItem, SummaryCellItem, SummaryGroupItem, @@ -26,6 +27,8 @@ import { getSummaryItemIndex } from '../utils/get_summary_item_index'; export const summaryDataControllerExtender = ( Base: ModuleType, ): ModuleType => class SummaryDataControllerExtender extends Base { + public declare _dataSource?: SummaryDataSourceAdapter | null; + private _footerItems!: FooterItem[]; public init(): void { @@ -43,8 +46,7 @@ export const summaryDataControllerExtender = ( public getTotalSummaryValue(summaryItemName?: string | number | null): unknown { const summaryItemIndex = getSummaryItemIndex(this.option('summary.totalItems'), summaryItemName); - // @ts-expect-error badly typed DataSourceAdapter - const aggregates = this._dataSource.totalAggregates(); + const aggregates = this._dataSource?.totalAggregates() ?? []; if (aggregates.length && summaryItemIndex > -1) { return aggregates[summaryItemIndex]; @@ -294,7 +296,6 @@ export const summaryDataControllerExtender = ( this._footerItems = []; if (dataSource && summaryTotalItems?.length) { - // @ts-expect-error badly typed DataSourceAdapter const totalAggregates = dataSource.totalAggregates(); const summaryCells = this._getSummaryCells(summaryTotalItems, totalAggregates); diff --git a/packages/devextreme/js/__internal/grids/data_grid/summary/m_summary.ts b/packages/devextreme/js/__internal/grids/data_grid/summary/m_summary.ts index 04cdd157df6f..ae41bfd59199 100644 --- a/packages/devextreme/js/__internal/grids/data_grid/summary/m_summary.ts +++ b/packages/devextreme/js/__internal/grids/data_grid/summary/m_summary.ts @@ -32,6 +32,8 @@ import { import type { Aggregate, SummaryOptions } from './types'; import { getSummaryOptions } from './utils/get_summary_options'; +export type SummaryDataSourceAdapter = InstanceType>; + export const renderSummaryCell = function (cell, options, setAria) { const $cell = $(cell); const { column } = options; @@ -256,7 +258,7 @@ export class FooterView extends ColumnsView { export const summaryDataSourceAdapterExtender = ( Base: ModuleType, -): ModuleType => class SummaryDataSourceAdapterExtender +) => class SummaryDataSourceAdapterExtender extends Base implements EditingControllerRequired { private _totalAggregates!: unknown[]; 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 8f100ff68974..a59abef02616 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 @@ -187,7 +187,7 @@ export class DataController extends modules.Controller { */ protected _getPagingOptionValue(optionName: PagingOptionName): number { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this._dataSource![optionName]() as number; + return this._dataSource![optionName](); } protected callbackNames(): string[] { @@ -1586,7 +1586,7 @@ export class DataController extends modules.Controller { } if (value === undefined) { - return dataSource[optionName]() as number; + return dataSource[optionName](); } const oldValue = this._getPagingOptionValue(optionName); @@ -1606,8 +1606,7 @@ export class DataController extends modules.Controller { this._skipProcessingPagingChange = false; } - // @ts-expect-error badly typed DataSourceAdapter - const pageIndex: number = dataSource.pageIndex(); + const pageIndex = dataSource.pageIndex(); this._isPaging = optionName === 'pageIndex'; const loadResult: DeferredObj = dataSource[optionName === 'pageIndex' ? 'load' : 'reload'](); @@ -1757,9 +1756,8 @@ export class DataController extends modules.Controller { return this._dataSource?.reload(reload, changesOnly) as DeferredObj; } - public push(...args: unknown[]): unknown { - // @ts-expect-error badly typed DataSourceAdapter - return this._dataSource?.push(...args); + public push(changes: StoreChange[], fromStore = false): void { + this._dataSource?.push(changes, fromStore); } private itemsCount(): number { @@ -1778,7 +1776,7 @@ export class DataController extends modules.Controller { * @extended: state_storing */ public isLoaded(): boolean { - return (this._dataSource ? this._dataSource.isLoaded() : true) as boolean; + return (this._dataSource ? this._dataSource.isLoaded() : true); } public totalCount(): number { diff --git a/packages/devextreme/js/__internal/grids/grid_core/data_controller/types.ts b/packages/devextreme/js/__internal/grids/grid_core/data_controller/types.ts index fb56b2e9dd66..aef85ec9a842 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/data_controller/types.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/data_controller/types.ts @@ -1,7 +1,6 @@ import type { SearchOperation } from '@js/common/data.types'; import type { ScalarFilterValue } from '@js/common/grids'; import type { DeferredObj } from '@js/core/utils/deferred'; -import type { DataSource } from '@ts/data/data_source/types'; import type { Column } from '../columns_controller/types'; import type { ChangedEvent, OperationTypes, RawItemData } from '../data_source_adapter/types'; @@ -142,12 +141,6 @@ export type ItemChange = | { type: 'insert'; index: number; data: ProcessedItem | { type: 'update'; index: number; data: ProcessedItem; oldItem: ProcessedItem } | { type: 'remove'; index: number; oldItem: ProcessedItem }; -/** data source */ - -export interface DataSourceAdapterLike { - _dataSource: DataSource; -} - /** callbacks */ export interface CallbackFlags { diff --git a/packages/devextreme/js/__internal/grids/grid_core/data_source_adapter/m_data_source_adapter.ts b/packages/devextreme/js/__internal/grids/grid_core/data_source_adapter/m_data_source_adapter.ts index e25b4bc85757..e83c5065b964 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/data_source_adapter/m_data_source_adapter.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/data_source_adapter/m_data_source_adapter.ts @@ -254,7 +254,7 @@ export default class DataSourceAdapter extends modules.Controller { } } - public resetCurrentTotalCount() { + public resetCurrentTotalCount(): void { this._currentTotalCount = 0; this._totalCountCorrection = 0; } @@ -799,9 +799,11 @@ export default class DataSourceAdapter extends modules.Controller { * @extended: TreeLists's data_source_adapter */ // eslint-disable-next-line @typescript-eslint/no-unused-vars - public changeRowExpand(path?: any): any {} + public changeRowExpand(path?: unknown): DeferredObj | undefined { + return undefined; + } - public totalCount() { + public totalCount(): number { // eslint-disable-next-line radix return parseInt((this._currentTotalCount || this._dataSourceTotalCount()) + this._totalCountCorrection); } @@ -819,14 +821,14 @@ export default class DataSourceAdapter extends modules.Controller { /** * @extended: virtual_scrolling */ - public itemsCount() { + public itemsCount(): number { return this._dataSource.items().length; } /** * @extended: TreeLists's data_source_adapter */ - public totalItemsCount() { + public totalItemsCount(): number { return this.totalCount(); } @@ -841,7 +843,7 @@ export default class DataSourceAdapter extends modules.Controller { return this._dataSource.pageSize(value); } - public pageCount() { + public pageCount(): number { const count = this.totalItemsCount() - this._totalCountCorrection; const pageSize = this.pageSize(); @@ -851,7 +853,7 @@ export default class DataSourceAdapter extends modules.Controller { return 1; } - public hasKnownLastPage() { + public hasKnownLastPage(): boolean { return this._hasLastPage || this._dataSource.totalCount() >= 0; } @@ -905,11 +907,15 @@ export default class DataSourceAdapter extends modules.Controller { /** * @exended: virtual_scrolling */ - public isLoaded(): any {} + public isLoaded(): boolean { + return this._dataSource.isLoaded(); + } /** * @extended: virtual_scrolling */ + public pageIndex(): number; + public pageIndex(pageIndex: number): void; // eslint-disable-next-line @typescript-eslint/no-unused-vars - public pageIndex(pageIndex?) {} + public pageIndex(pageIndex?: number): number | void {} } diff --git a/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/extenders/virtual_scrolling_data_controller.ts b/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/extenders/virtual_scrolling_data_controller.ts index a2b752e7aeec..e7638bc1eb21 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/extenders/virtual_scrolling_data_controller.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/extenders/virtual_scrolling_data_controller.ts @@ -34,7 +34,7 @@ import { LOAD_TIMEOUT, VISIBLE_PAGE_INDEX, } from '../const'; -import type { dataSourceAdapterExtender } from '../m_virtual_scrolling'; +import type { VirtualScrollingDataSourceAdapter } from '../m_virtual_scrolling'; import { VirtualScrollController } from '../m_virtual_scrolling_core'; import type { ChangedLoadParams } from '../types'; import type { GroupCountableDataSource } from '../utils/items'; @@ -53,8 +53,6 @@ export interface VirtualScrollingDataControllerExtension { virtualItemsCount: () => VirtualItemsCount | undefined; } -type VirtualScrollingDataSourceAdapter = InstanceType>; - export const virtualScrollingDataControllerExtender = ( Base: ModuleType, ): ModuleType< @@ -112,7 +110,6 @@ export const virtualScrollingDataControllerExtender = ( // eslint-disable-next-line @typescript-eslint/no-unused-vars public reload(reload?: boolean, changesOnly?: boolean): DeferredObj { const rowsScrollController = this._rowsScrollController || this._dataSource; - // @ts-expect-error badly typed DataSourceAdapter const itemIndex = rowsScrollController?.getItemIndexByPosition(); const result = super.reload.apply(this, arguments as any); return result?.done(() => { diff --git a/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/index.ts b/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/index.ts index 0d897b8aa8af..2171593231d5 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/index.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/index.ts @@ -2,5 +2,10 @@ export { virtualScrollingDataControllerExtender, type VirtualScrollingDataControllerExtension, } from './extenders/virtual_scrolling_data_controller'; -export { dataSourceAdapterExtender, resizing, rowsView } from './m_virtual_scrolling'; +export { + dataSourceAdapterExtender, + resizing, + rowsView, + type VirtualScrollingDataSourceAdapter, +} from './m_virtual_scrolling'; export { virtualScrollingModule } from './virtual_scrolling_module'; diff --git a/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts b/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts index 094de621b840..59e0216107dd 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts @@ -37,6 +37,8 @@ import type { GroupCountableDataSource } from './utils/items'; import { isItemCountableByDataSource } from './utils/items'; import { isInfiniteMode, isVirtualMode, isVirtualPaging } from './utils/scrolling_mode'; +export type VirtualScrollingDataSourceAdapter = InstanceType>; + export const updateLoading = function (that) { const beginPageIndex = that._virtualScrollController.beginPageIndex(-1); @@ -87,9 +89,9 @@ export const dataSourceAdapterExtender = (Base: ModuleType) = private _loadPageCount: any; - private _virtualScrollController!: VirtualScrollController; + public _virtualScrollController!: VirtualScrollController; - private readonly _renderTime: any; + public _renderTime = 0; private _isLoading: any; @@ -579,7 +581,7 @@ export const rowsView = (Base: ModuleType) => class VirtualScrollingRo const deferred = super._renderCore.apply(this, arguments as any); - const dataSource = this._dataController._dataSource; + const dataSource = this._dataController._dataSource as VirtualScrollingDataSourceAdapter | null | undefined; if (dataSource && e) { const itemCount = e.items ? e.items.length : 20; @@ -588,10 +590,8 @@ export const rowsView = (Base: ModuleType) => class VirtualScrollingRo .viewportSize() || 20; if (gridCoreUtils.isVirtualRowRendering(this) && itemCount > 0 && this.option(LEGACY_SCROLLING_MODE) !== false) { - // @ts-expect-error badly typed DataSourceAdapter dataSource._renderTime = (Date.now() - startRenderTime) * viewportSize / itemCount; } else { - // @ts-expect-error badly typed DataSourceAdapter dataSource._renderTime = Date.now() - startRenderTime; } } diff --git a/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling_core.ts b/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling_core.ts index eac3dca33055..58dee2c2ea30 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling_core.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling_core.ts @@ -232,7 +232,7 @@ class VirtualScrollController { return this._position; } - private getItemIndexByPosition(position?, viewportItemIndex?, height?) { + public getItemIndexByPosition(position?, viewportItemIndex?, height?) { position = position ?? this._position; const defaultItemSize = this.getItemSize(); let offset = 0; diff --git a/packages/devextreme/js/__internal/grids/tree_list/data_controller/m_data_controller.ts b/packages/devextreme/js/__internal/grids/tree_list/data_controller/m_data_controller.ts index 55c9e35e78fa..4292d4bc1832 100644 --- a/packages/devextreme/js/__internal/grids/tree_list/data_controller/m_data_controller.ts +++ b/packages/devextreme/js/__internal/grids/tree_list/data_controller/m_data_controller.ts @@ -166,7 +166,6 @@ export class TreeListDataController extends DataController { break; case 'expandedRowKeys': case 'onNodesInitialized': - // @ts-expect-error badly typed DataSourceAdapter if (this._dataSource && !this._dataSource._isNodesInitializing && !equalByValue(args.value, args.previousValue)) { this._loadOnOptionChange(); } diff --git a/packages/devextreme/js/__internal/grids/tree_list/data_source_adapter/m_data_source_adapter.ts b/packages/devextreme/js/__internal/grids/tree_list/data_source_adapter/m_data_source_adapter.ts index 794e20ebb1bd..9905f8fda6e8 100644 --- a/packages/devextreme/js/__internal/grids/tree_list/data_source_adapter/m_data_source_adapter.ts +++ b/packages/devextreme/js/__internal/grids/tree_list/data_source_adapter/m_data_source_adapter.ts @@ -71,7 +71,7 @@ export class DataSourceAdapterTreeList extends DataSourceAdapter { private _rootNode: any; - private _isNodesInitializing: any; + public _isNodesInitializing = false; private _totalItemsCount: any; diff --git a/packages/devextreme/js/__internal/grids/tree_list/m_focus.ts b/packages/devextreme/js/__internal/grids/tree_list/m_focus.ts index 976b33b0d7d0..fd416428dedc 100644 --- a/packages/devextreme/js/__internal/grids/tree_list/m_focus.ts +++ b/packages/devextreme/js/__internal/grids/tree_list/m_focus.ts @@ -85,11 +85,9 @@ const data = ( that.getParentKey(key).done((parentKey) => { if (dataSource && parentKey !== undefined && parentKey !== that.option('rootValue')) { - // @ts-expect-error badly typed DataSourceAdapter dataSource._isNodesInitializing = true; // @ts-expect-error that.expandRow(parentKey); - // @ts-expect-error badly typed DataSourceAdapter dataSource._isNodesInitializing = false; that.expandAscendants(parentKey).done(d.resolve).fail(d.reject); } else { diff --git a/packages/devextreme/js/__internal/grids/tree_list/m_virtual_scrolling.ts b/packages/devextreme/js/__internal/grids/tree_list/m_virtual_scrolling.ts index 169ec0172d0a..cb9629f34d9b 100644 --- a/packages/devextreme/js/__internal/grids/tree_list/m_virtual_scrolling.ts +++ b/packages/devextreme/js/__internal/grids/tree_list/m_virtual_scrolling.ts @@ -9,6 +9,7 @@ import { dataSourceAdapterExtender as virtualScrollingDataSourceAdapterExtender, rowsView as virtualScrollingRowsViewExtender, virtualScrollingDataControllerExtender, + type VirtualScrollingDataSourceAdapter, virtualScrollingModule, } from '@ts/grids/grid_core/virtual_scrolling/index'; @@ -34,8 +35,9 @@ virtualScrollingModule.extenders.views.rowsView = (Base: ModuleType) = }; virtualScrollingModule.extenders.controllers.data = (Base: ModuleType) => class TreeListVirtualScrollingDataControllerExtender extends virtualScrollingDataControllerExtender(Base) { + public declare _dataSource?: VirtualScrollingDataSourceAdapter | null; + protected _loadOnOptionChange() { - // @ts-expect-error badly typed DataSourceAdapter const virtualScrollController = this._dataSource?._virtualScrollController; virtualScrollController?.reset(); @@ -46,7 +48,7 @@ virtualScrollingModule.extenders.controllers.data = (Base: ModuleType) => class VirtualScrollingDataSourceAdapterExtender extends virtualScrollingDataSourceAdapterExtender(Base) { public changeRowExpand() { - return super.changeRowExpand.apply(this, arguments as any).done(() => { + return super.changeRowExpand.apply(this, arguments as any)?.done(() => { const viewportItemIndex = this.getViewportItemIndex(); viewportItemIndex >= 0 && this.setViewportItemIndex(viewportItemIndex); From b2509f93912e5b1bc20d8c46797efb246dff996d Mon Sep 17 00:00:00 2001 From: Maksim Zakharov <251575087+bit-byte0@users.noreply.github.com> Date: Wed, 2 Sep 2026 13:56:32 +0400 Subject: [PATCH 2/4] refactor(treeList): narrow focus _dataSource to drop adapter casts --- .../js/__internal/grids/tree_list/m_focus.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/devextreme/js/__internal/grids/tree_list/m_focus.ts b/packages/devextreme/js/__internal/grids/tree_list/m_focus.ts index fd416428dedc..75b53ec9147d 100644 --- a/packages/devextreme/js/__internal/grids/tree_list/m_focus.ts +++ b/packages/devextreme/js/__internal/grids/tree_list/m_focus.ts @@ -21,6 +21,8 @@ function findIndex(items, callback) { const data = ( Base: ModuleType, ) => class TreeListDataControllerExtender extends focusModule.extenders.controllers.data(Base) { + public declare _dataSource?: DataSourceAdapterTreeList | null; + private changeRowExpand(key) { // @ts-expect-error if (this.option('focusedRowEnabled') && this.isRowExpanded(key)) { @@ -52,7 +54,7 @@ const data = ( private getParentKey(key) { const that = this; - const dataSource = that._dataSource as unknown as DataSourceAdapterTreeList; + const dataSource = that._dataSource!; // @ts-expect-error const node = that.getNodeByKey(key); // @ts-expect-error @@ -79,7 +81,7 @@ const data = ( private expandAscendants(key) { const that = this; - const dataSource = that._dataSource as unknown as DataSourceAdapterTreeList; + const dataSource = that._dataSource; // @ts-expect-error const d = new Deferred(); @@ -99,7 +101,7 @@ const data = ( } protected getPageIndexByKey(key) { - const dataSource = this._dataSource as unknown as DataSourceAdapterTreeList; + const dataSource = this._dataSource!; // @ts-expect-error const d = new Deferred(); @@ -107,7 +109,7 @@ const data = ( dataSource.load({ parentIds: [], }).done((nodes) => { - if ((this._dataSource as unknown) !== (dataSource as unknown)) { + if (this._dataSource !== dataSource) { d.resolve(-1); return; } From 58ccbd4d7c233caf1029380d5f68670dc7d38c2b Mon Sep 17 00:00:00 2001 From: Maksim Zakharov <251575087+bit-byte0@users.noreply.github.com> Date: Wed, 2 Sep 2026 22:45:04 +0400 Subject: [PATCH 3/4] refactor(dataSourceAdapter): type remaining public methods and DataController.dataSource() --- .../data_controller/data_controller.ts | 14 ++--- .../m_data_source_adapter.ts | 56 ++++++++++--------- .../grid_core/data_source_adapter/types.ts | 13 +++++ .../grid_core/filter_panel/m_filter_panel.ts | 2 +- .../virtual_scrolling_data_controller.ts | 13 +++-- .../virtual_scrolling/m_virtual_scrolling.ts | 2 +- .../data_controller/m_data_controller.ts | 10 ++-- .../m_data_source_adapter.ts | 19 ++++--- .../grids/tree_list/editing/m_editing.ts | 11 ++-- .../grids/tree_list/m_virtual_scrolling.ts | 4 +- 10 files changed, 82 insertions(+), 62 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 a59abef02616..8f93e8e98725 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 @@ -1179,7 +1179,8 @@ export class DataController extends modules.Controller { // change.items at this stage is defined only if virtualScrolling // + legacyScrollingMode enabled // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const dataItems = this._beforeProcessItems(change.items ?? this._dataSource!.items()); + const items = (change.items ?? this._dataSource!.items()) as RawItemData[]; + const dataItems = this._beforeProcessItems(items); const processedItems = this._processItems(dataItems, change); this._cachedProcessedItems = processedItems; @@ -1240,7 +1241,7 @@ export class DataController extends modules.Controller { return; } - const operationTypes: OperationTypes | undefined = this.dataSource().operationTypes(); + const operationTypes = this.dataSource()?.operationTypes() ?? undefined; change.isDataChanged = true; change.repaintChangesOnly = resolveRepaintChangesOnly( @@ -1471,13 +1472,12 @@ export class DataController extends modules.Controller { return this._dataSource ? this._dataSource.pageCount() : 1; } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - public dataSource(): any { - return this._dataSource; + public dataSource(): DataSourceAdapter | undefined { + return this._dataSource ?? undefined; } public store(): Store | undefined { - return this._dataSource?.store() as Store | undefined; + return this._dataSource?.store(); } public loadAll(data?: RawItemData[], skipFilter = false): DeferredObj { @@ -1732,7 +1732,7 @@ export class DataController extends modules.Controller { } public getCachedStoreData(): RawItemData[] | undefined { - return this._dataSource?.getCachedStoreData() as RawItemData[] | undefined; + return this._dataSource?.getCachedStoreData(); } /** diff --git a/packages/devextreme/js/__internal/grids/grid_core/data_source_adapter/m_data_source_adapter.ts b/packages/devextreme/js/__internal/grids/grid_core/data_source_adapter/m_data_source_adapter.ts index e83c5065b964..22ed0a95986f 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/data_source_adapter/m_data_source_adapter.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/data_source_adapter/m_data_source_adapter.ts @@ -1,4 +1,5 @@ /* eslint-disable @typescript-eslint/no-dynamic-delete */ +import type { Store } from '@js/common/data'; import ArrayStore from '@js/common/data/array_store'; import { applyBatch } from '@js/common/data/array_utils'; import type { Callback } from '@js/core/utils/callbacks'; @@ -10,6 +11,7 @@ import { extend } from '@js/core/utils/extend'; import { each } from '@js/core/utils/iterator'; import { isDefined, isPlainObject } from '@js/core/utils/type'; import type { StoreChange } from '@js/data/store'; +import type { StoreKey } from '@ts/data/abstract_store'; import type { ChangingEvent, DataSource, StoreLoadOptions } from '@ts/data/data_source/types'; import type { BeforePushEvent } from '@ts/data/types'; @@ -203,13 +205,11 @@ export default class DataSourceAdapter extends modules.Controller { return (this._dataSource.requireTotalCount as (...a: unknown[]) => unknown)(value); } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - public store(): any { + public store(): Store { return this._dataSource.store(); } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - public key(): any { + public key(): StoreKey | undefined { return this._dataSource.key(); } @@ -244,7 +244,7 @@ export default class DataSourceAdapter extends modules.Controller { /** * @extended: virtual_scrolling */ - public refresh(options, operationTypes) { + public refresh(options: LoadOperation, operationTypes: OperationTypes): void { const dataSource = this._dataSource; if (operationTypes.reload) { @@ -314,7 +314,7 @@ export default class DataSourceAdapter extends modules.Controller { this.pushed.fire(changes); } - public getDataIndexGetter() { + public getDataIndexGetter(): (data: RawItemData) => number { if (!this._dataIndexGetter) { const store = this.store(); @@ -574,9 +574,9 @@ export default class DataSourceAdapter extends modules.Controller { /** * @extended: TreeLists's data_source_adapter */ - public customizeLoadResultHandler(options) { + public customizeLoadResultHandler(options: LoadOperation): void { const { loadOptions } = options; - const localPaging = options.remoteOperations && !options.remoteOperations.paging; + const localPaging = options.remoteOperations && !(options.remoteOperations as RemoteOperationsOptions).paging; const { cachedData } = options; const { storeLoadOptions } = options; const needCache = this.option('cacheEnabled') !== false && storeLoadOptions; @@ -585,7 +585,7 @@ export default class DataSourceAdapter extends modules.Controller { const needStoreCache = needPagingCache && !options.isCustomLoading; if (!loadOptions) { - this._dataSource.cancel(options.operationId); + this._dataSource.cancel(options.operationId!); return; } @@ -598,17 +598,17 @@ export default class DataSourceAdapter extends modules.Controller { } if (loadOptions.group) { - loadOptions.group = options.group || loadOptions.group; + loadOptions.group = (options.group as StoreLoadOptions['group']) || loadOptions.group; } const groupCount = gridCoreUtils.normalizeSortingInfo(options.group || storeLoadOptions.group || loadOptions.group).length; if (options.cachedDataPartBegin) { - options.data = options.cachedDataPartBegin.concat(options.data); + options.data = options.cachedDataPartBegin.concat(options.data as RawItemData[]); } if (options.cachedDataPartEnd) { - options.data = options.data.concat(options.cachedDataPartEnd); + options.data = (options.data as RawItemData[]).concat(options.cachedDataPartEnd); } if (!needPageCache || !getPageDataFromCache(options)) { @@ -623,8 +623,8 @@ export default class DataSourceAdapter extends modules.Controller { options.data = this._cachedStoreData; } } - new ArrayStore(options.data).load(loadOptions).done((data) => { - options.data = data; + new ArrayStore(options.data as RawItemData[]).load(loadOptions).done((data) => { + options.data = data as RawItemData[]; if (needStoreCache) { this._cachedPagingData = cloneItems(options.data, groupCount); } @@ -636,10 +636,10 @@ export default class DataSourceAdapter extends modules.Controller { if (loadOptions.requireTotalCount && localPaging) { options.extra = isPlainObject(options.extra) ? options.extra : {}; - options.extra.totalCount = options.data.length; + options.extra.totalCount = (options.data as RawItemData[]).length; } - if (options.extra && options.extra.totalCount >= 0 && (storeLoadOptions.requireTotalCount === false || loadOptions.requireTotalCount === false)) { + if (options.extra && (options.extra.totalCount ?? -1) >= 0 && (storeLoadOptions.requireTotalCount === false || loadOptions.requireTotalCount === false)) { options.extra.totalCount = -1; } @@ -661,13 +661,13 @@ export default class DataSourceAdapter extends modules.Controller { if (options.lastLoadOptions) { this._lastLoadOptions = options.lastLoadOptions; - Object.keys(options.operationTypes).forEach((operationType) => { + Object.keys(options.operationTypes ?? {}).forEach((operationType) => { // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - this._lastOperationTypes[operationType] ||= options.operationTypes[operationType]; + this._lastOperationTypes[operationType] ||= options.operationTypes?.[operationType]; }); } }); - options.storeLoadOptions = options.originalStoreLoadOptions; + options.storeLoadOptions = options.originalStoreLoadOptions as typeof options.storeLoadOptions; } /** @@ -766,7 +766,7 @@ export default class DataSourceAdapter extends modules.Controller { } } - private loadingOperationTypes() { + public loadingOperationTypes(): OperationTypes | undefined { return this._loadingOperationTypes; } @@ -774,7 +774,7 @@ export default class DataSourceAdapter extends modules.Controller { return this._operationTypes ?? null; } - public lastLoadOptions() { + public lastLoadOptions(): NonNullable { return this._lastLoadOptions || {}; } @@ -808,7 +808,7 @@ export default class DataSourceAdapter extends modules.Controller { return parseInt((this._currentTotalCount || this._dataSourceTotalCount()) + this._totalCountCorrection); } - public totalCountCorrection() { + public totalCountCorrection(): number { return this._totalCountCorrection; } @@ -816,7 +816,9 @@ export default class DataSourceAdapter extends modules.Controller { * @extended: virtual_scrolling * @protected */ - public items(): any {} + public items(): RawItemData[] { + return (this._items ?? []) as RawItemData[]; + } /** * @extended: virtual_scrolling @@ -832,9 +834,9 @@ export default class DataSourceAdapter extends modules.Controller { return this.totalCount(); } - protected pageSize(): number; - protected pageSize(value: number): void; - protected pageSize(value?: number): number | void { + public pageSize(): number; + public pageSize(value: number): void; + public pageSize(value?: number): number | void { if (value === undefined) { return this._dataSource.paginate() ? this._dataSource.pageSize() @@ -900,7 +902,7 @@ export default class DataSourceAdapter extends modules.Controller { return result as unknown as DeferredObj; } - public getCachedStoreData() { + public getCachedStoreData(): RawItemData[] | undefined { return this._cachedStoreData; } diff --git a/packages/devextreme/js/__internal/grids/grid_core/data_source_adapter/types.ts b/packages/devextreme/js/__internal/grids/grid_core/data_source_adapter/types.ts index bf7d03fe9217..08d6fa7a46f4 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/data_source_adapter/types.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/data_source_adapter/types.ts @@ -52,6 +52,19 @@ export interface LoadOperation extends Omit { totalCount?: number; summary?: unknown[]; }; + cachedData?: { + items: Record; + extra?: { + totalCount?: number; + summary?: unknown[]; + }; + }; + cachedPagingData?: RawItemData[]; + cachedDataPartBegin?: RawItemData[]; + cachedDataPartEnd?: RawItemData[]; + skip?: number; + take?: number; + mergeStoreLoadData?: boolean; } export interface ChangedEvent extends BaseChangedEvent { diff --git a/packages/devextreme/js/__internal/grids/grid_core/filter_panel/m_filter_panel.ts b/packages/devextreme/js/__internal/grids/grid_core/filter_panel/m_filter_panel.ts index 5d44c0c28f3a..c25f156bd2df 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/filter_panel/m_filter_panel.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/filter_panel/m_filter_panel.ts @@ -46,7 +46,7 @@ export class FilterPanelView extends modules.View { } public isVisible() { - return this.option('filterPanel.visible') && this._dataController.dataSource(); + return !!(this.option('filterPanel.visible') && this._dataController.dataSource()); } protected _renderCore() { diff --git a/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/extenders/virtual_scrolling_data_controller.ts b/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/extenders/virtual_scrolling_data_controller.ts index e7638bc1eb21..2c0b779ecba8 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/extenders/virtual_scrolling_data_controller.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/extenders/virtual_scrolling_data_controller.ts @@ -118,7 +118,7 @@ export const virtualScrollingDataControllerExtender = ( const rowIndex = Math.floor(itemIndex) - rowIndexOffset; const { component } = this; const scrollable = component.getScrollable && component.getScrollable(); - const isSortingOperation = this.dataSource().operationTypes().sorting; + const isSortingOperation = this.dataSource()?.operationTypes()?.sorting; if (scrollable && !isSortingOperation && rowIndex >= 0) { const rowElement = component.getRowElement(rowIndex); @@ -256,7 +256,7 @@ export const virtualScrollingDataControllerExtender = ( let result = that._items; if (that.option(LEGACY_SCROLLING_MODE)) { - const dataSource = that.dataSource(); + const dataSource = that._dataSource; const virtualItemsCount = dataSource?.virtualItemsCount(); const begin = virtualItemsCount ? virtualItemsCount.begin : 0; const rowPageSize = that.getRowPageSize(); @@ -289,7 +289,7 @@ export const virtualScrollingDataControllerExtender = ( onChanged() { }, changingDuration() { - const dataSource = that.dataSource(); + const dataSource = that._dataSource; if (dataSource?.isLoading() && that.option(LEGACY_SCROLLING_MODE) !== false) { return LOAD_TIMEOUT; @@ -486,7 +486,7 @@ export const virtualScrollingDataControllerExtender = ( public getRowIndexOffset(byLoadedRows?, needGroupOffset?) { let offset = 0; - const dataSource = this.dataSource(); + const dataSource = this._dataSource; const rowsScrollController = this._rowsScrollController; const newMode = this.option(LEGACY_SCROLLING_MODE) === false; const virtualPaging = isVirtualPaging(this); @@ -506,8 +506,9 @@ export const virtualScrollingDataControllerExtender = ( } else if (virtualPaging && newMode && dataSource) { const lastLoadOptions = dataSource.lastLoadOptions(); - if (needGroupOffset && lastLoadOptions.skips?.length) { - offset = lastLoadOptions.skips.reduce((res: number, skip: number) => res + skip, 0); + const { skips } = lastLoadOptions as { skips?: number[] }; + if (needGroupOffset && skips?.length) { + offset = skips.reduce((res: number, skip: number) => res + skip, 0); } else { offset = lastLoadOptions.skip ?? 0; } diff --git a/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts b/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts index 59e0216107dd..0feef3aadd61 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/virtual_scrolling/m_virtual_scrolling.ts @@ -348,7 +348,7 @@ export const dataSourceAdapterExtender = (Base: ModuleType) = return super._loadPageSize.apply(this, arguments as any) * this.loadPageCount(); } - private beginPageIndex(): any { + public beginPageIndex(): number { return proxyDataSourceAdapterMethod(this, 'beginPageIndex', [...arguments]); } diff --git a/packages/devextreme/js/__internal/grids/tree_list/data_controller/m_data_controller.ts b/packages/devextreme/js/__internal/grids/tree_list/data_controller/m_data_controller.ts index 4292d4bc1832..e87ee434b1e8 100644 --- a/packages/devextreme/js/__internal/grids/tree_list/data_controller/m_data_controller.ts +++ b/packages/devextreme/js/__internal/grids/tree_list/data_controller/m_data_controller.ts @@ -12,6 +12,10 @@ import treeListCore from '../m_core'; export class TreeListDataController extends DataController { public declare _dataSource?: DataSourceAdapterTreeList | null; + public dataSource(): DataSourceAdapterTreeList | undefined { + return this._dataSource ?? undefined; + } + protected _getDataSourceAdapterProvider(): DataSourceAdapterProvider { return dataSourceAdapterProvider; } @@ -88,11 +92,7 @@ export class TreeListDataController extends DataController { } public key() { - const dataSource = this._dataSource; - - if (dataSource) { - return dataSource.getKeyExpr(); - } + return this._dataSource?.getKeyExpr(); } public publicMethods() { diff --git a/packages/devextreme/js/__internal/grids/tree_list/data_source_adapter/m_data_source_adapter.ts b/packages/devextreme/js/__internal/grids/tree_list/data_source_adapter/m_data_source_adapter.ts index 9905f8fda6e8..e9a5cce5ffc1 100644 --- a/packages/devextreme/js/__internal/grids/tree_list/data_source_adapter/m_data_source_adapter.ts +++ b/packages/devextreme/js/__internal/grids/tree_list/data_source_adapter/m_data_source_adapter.ts @@ -1,3 +1,4 @@ +import type { Store } from '@js/common/data'; import ArrayStore from '@js/common/data/array_store'; import { createObjectWithChanges } from '@js/common/data/array_utils'; import query from '@js/common/data/query'; @@ -80,7 +81,7 @@ export class DataSourceAdapterTreeList extends DataSourceAdapter { private _createKeyGetter() { const keyExpr = this.getKeyExpr(); - return compileGetter(keyExpr); + return compileGetter(keyExpr as string); } private _createKeySetter() { @@ -90,21 +91,21 @@ export class DataSourceAdapterTreeList extends DataSourceAdapter { return keyExpr; } - return compileSetter(keyExpr); + return compileSetter(keyExpr as string); } - private createParentIdGetter() { - return compileGetter(this.option('parentIdExpr')); + public createParentIdGetter(): (data: unknown) => unknown { + return compileGetter(this.option('parentIdExpr')) as (data: unknown) => unknown; } - private createParentIdSetter() { + public createParentIdSetter(): (data: unknown, value: unknown) => void { const parentIdExpr = this.option('parentIdExpr'); if (isFunction(parentIdExpr)) { - return parentIdExpr; + return parentIdExpr as (data: unknown, value: unknown) => void; } - return compileSetter(parentIdExpr); + return compileSetter(parentIdExpr) as (data: unknown, value: unknown) => void; } private _createItemsGetter() { @@ -513,8 +514,8 @@ export class DataSourceAdapterTreeList extends DataSourceAdapter { protected _getKeyInfo() { return { key: () => 'key', - keyOf: (data) => data.key, - }; + keyOf: (data: { key: unknown }) => data.key, + } as Store; } private _processChanges(changes) { diff --git a/packages/devextreme/js/__internal/grids/tree_list/editing/m_editing.ts b/packages/devextreme/js/__internal/grids/tree_list/editing/m_editing.ts index e9cb486ebb7e..b3de51743303 100644 --- a/packages/devextreme/js/__internal/grids/tree_list/editing/m_editing.ts +++ b/packages/devextreme/js/__internal/grids/tree_list/editing/m_editing.ts @@ -14,6 +14,7 @@ import type { ModuleType } from '@ts/grids/grid_core/m_types'; import gridCoreUtils from '@ts/grids/grid_core/m_utils'; import type { RowsView } from '../../grid_core/views/m_rows_view'; +import type { TreeListDataController } from '../data_controller/m_data_controller'; import treeListCore from '../m_core'; const TREELIST_EXPAND_ICON_CONTAINER_CLASS = 'dx-treelist-icon-container'; @@ -22,6 +23,8 @@ const SELECT_CHECKBOX_CLASS = 'dx-select-checkbox'; const DATA_EDIT_DATA_INSERT_TYPE = 'insert'; class EditingController extends editingModule.controllers.editing { + protected declare _dataController: TreeListDataController; + protected _generateNewItem(key) { const item: any = super._generateNewItem(key); @@ -133,9 +136,9 @@ class EditingController extends editingModule.controllers.editing { protected _addRowCore(data, parentKey, oldEditRowIndex) { const rootValue = this.option('rootValue'); const dataSourceAdapter = this._dataController.dataSource(); - const parentKeyGetter = dataSourceAdapter.createParentIdGetter(); + const parentKeyGetter = dataSourceAdapter?.createParentIdGetter(); - parentKey = parentKeyGetter(data); + parentKey = parentKeyGetter?.(data); // @ts-expect-error if (parentKey !== undefined && parentKey !== rootValue && !this._dataController.isRowExpanded(parentKey)) { @@ -157,9 +160,9 @@ class EditingController extends editingModule.controllers.editing { protected _initNewRow(options, parentKey?) { const dataSourceAdapter = this._dataController.dataSource(); - const parentIdSetter = dataSourceAdapter.createParentIdSetter(); + const parentIdSetter = dataSourceAdapter?.createParentIdSetter(); - parentIdSetter(options.data, parentKey); + parentIdSetter?.(options.data, parentKey); // @ts-expect-error return super._initNewRow.apply(this, arguments); diff --git a/packages/devextreme/js/__internal/grids/tree_list/m_virtual_scrolling.ts b/packages/devextreme/js/__internal/grids/tree_list/m_virtual_scrolling.ts index cb9629f34d9b..5aa29b16ffc8 100644 --- a/packages/devextreme/js/__internal/grids/tree_list/m_virtual_scrolling.ts +++ b/packages/devextreme/js/__internal/grids/tree_list/m_virtual_scrolling.ts @@ -47,8 +47,8 @@ virtualScrollingModule.extenders.controllers.data = (Base: ModuleType) => class VirtualScrollingDataSourceAdapterExtender extends virtualScrollingDataSourceAdapterExtender(Base) { - public changeRowExpand() { - return super.changeRowExpand.apply(this, arguments as any)?.done(() => { + public changeRowExpand(path?: unknown) { + return super.changeRowExpand(path)?.done(() => { const viewportItemIndex = this.getViewportItemIndex(); viewportItemIndex >= 0 && this.setViewportItemIndex(viewportItemIndex); From ac7e265d852946934b140716d8d70b974f261364 Mon Sep 17 00:00:00 2001 From: Maksim Zakharov <251575087+bit-byte0@users.noreply.github.com> Date: Wed, 2 Sep 2026 23:54:52 +0400 Subject: [PATCH 4/4] fix(treeList): keep incoming parentKey when parent-id getter is absent --- .../js/__internal/grids/tree_list/editing/m_editing.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/devextreme/js/__internal/grids/tree_list/editing/m_editing.ts b/packages/devextreme/js/__internal/grids/tree_list/editing/m_editing.ts index b3de51743303..7c23b3a932b7 100644 --- a/packages/devextreme/js/__internal/grids/tree_list/editing/m_editing.ts +++ b/packages/devextreme/js/__internal/grids/tree_list/editing/m_editing.ts @@ -138,7 +138,7 @@ class EditingController extends editingModule.controllers.editing { const dataSourceAdapter = this._dataController.dataSource(); const parentKeyGetter = dataSourceAdapter?.createParentIdGetter(); - parentKey = parentKeyGetter?.(data); + parentKey = parentKeyGetter ? parentKeyGetter(data) : parentKey; // @ts-expect-error if (parentKey !== undefined && parentKey !== rootValue && !this._dataController.isRowExpanded(parentKey)) {