Skip to content

Commit aa72721

Browse files
vorobeyAndrei VorobevCopilot
authored
Autocomplete, DropdownButton, Dropdownbox: refactor types (#33922)
Signed-off-by: Andrey Vorobev <dobriy.kaa@gmail.com> Co-authored-by: Andrei Vorobev <andrei.vorobev@devexpress.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
1 parent 24ca922 commit aa72721

12 files changed

Lines changed: 325 additions & 265 deletions

File tree

packages/devextreme/js/__internal/core/widget/widget.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -427,8 +427,7 @@ class Widget<
427427
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
428428
keyboardListeners.forEach((listener) => listener?._keyboardHandler(options));
429429

430-
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
431-
onKeyboardHandled && onKeyboardHandled(options);
430+
onKeyboardHandled?.(options);
432431

433432
return true;
434433
}
@@ -570,13 +569,12 @@ class Widget<
570569
this.$element().toggleClass('dx-state-independent', ignoreParentReadOnly);
571570
}
572571

573-
_setWidgetOption(widgetName: string, args: Record<string, unknown>): void {
572+
_setWidgetOption(widgetName: string, args: [string, unknown?] | [Record<string, unknown>]): void {
574573
if (!this[widgetName]) {
575574
return;
576575
}
577576

578577
if (isPlainObject(args[0])) {
579-
// @ts-expect-error
580578
each(args[0], (option, value) => this._setWidgetOption(widgetName, [option, value]));
581579

582580
return;

packages/devextreme/js/__internal/data/data_controller/data_controller.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { normalizeDataSourceOptions } from '../../../common/data/data_source/uti
66
import { extend } from '../../../core/utils/extend';
77
import { isDefined } from '../../../core/utils/type';
88

9-
interface DataSourceType {
9+
export interface DataSourceType {
1010
_userData: unknown;
1111
_pageSize: number;
1212
dispose: () => void;
@@ -47,7 +47,6 @@ interface DataControllerOptions extends Record<string, unknown> {
4747
class DataController {
4848
private _isSharedDataSource = false;
4949

50-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
5150
// @ts-expect-error
5251
private _dataSource: DataSourceType;
5352

@@ -75,7 +74,6 @@ class DataController {
7574
}
7675

7776
_updateDataSourceByItems(items: unknown[]): void {
78-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
7977
this._dataSource = new DataSource({
8078
store: new ArrayStore({
8179
key: this.key(),
@@ -93,7 +91,6 @@ class DataController {
9391
this._dataSource.dispose();
9492
}
9593

96-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
9794
// @ts-expect-error
9895
delete this._dataSource;
9996
}
@@ -126,9 +123,7 @@ class DataController {
126123
}
127124

128125
loadNextPage(): Promise<unknown> {
129-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
130126
// @ts-expect-error
131-
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
132127
this.pageIndex(1 + this.pageIndex());
133128

134129
return this.load();
@@ -189,7 +184,7 @@ class DataController {
189184
}
190185
}
191186

192-
updateDataSource(items: unknown[] | DataSourceType, key?: string): void {
187+
updateDataSource(items?: unknown[] | DataSourceType, key?: string): void {
193188
const dataSourceOptions = items ?? this.items();
194189

195190
if (key) {

packages/devextreme/js/__internal/events/utils/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ export const isPointerEvent = (e) => eventSource(e) === 'pointer';
9898
export const isMouseEvent = (e) => isNativeMouseEvent(e)
9999
|| ((isPointerEvent(e) || isDxEvent(e)) && e.pointerType === 'mouse');
100100

101-
export const isDxMouseWheelEvent = (e) => e && e.type === 'dxmousewheel';
101+
export const isDxMouseWheelEvent = (e) => e?.type === 'dxmousewheel';
102102

103103
export const isTouchEvent = (e) => isNativeTouchEvent(e)
104104
|| ((isPointerEvent(e) || isDxEvent(e)) && e.pointerType === 'touch');

packages/devextreme/js/__internal/ui/drop_down_editor/drop_down_editor.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -912,7 +912,7 @@ class DropDownEditor<
912912
toolbarItems: this._getPopupToolbarItems(),
913913
onPositioned: this._popupPositionedHandler.bind(this),
914914
fullScreen: false,
915-
// @ts-expect-error should be added on Popup level
915+
// @ts-expect-error Should be updated on public PopupProperties level
916916
contentTemplate: null,
917917
_hideOnParentScrollTarget: this.$element(),
918918
_wrapperClassExternal: DROP_DOWN_EDITOR_OVERLAY,
@@ -1043,7 +1043,6 @@ class DropDownEditor<
10431043
}
10441044

10451045
_setPopupOption(...args: [string, unknown?]): void {
1046-
// @ts-expect-error Should be fixed on Widget level
10471046
this._setWidgetOption('_popup', args);
10481047
}
10491048

packages/devextreme/js/__internal/ui/drop_down_editor/drop_down_list.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ interface DropDownListProperties extends Omit<dxDropDownListOptions<DropDownList
5757
displayCustomValue?: boolean;
5858
items?: Item[];
5959
}
60-
6160
class DropDownList<
6261
TProperties extends DropDownListProperties = DropDownListProperties,
6362
> extends DropDownEditor<TProperties> {
@@ -418,7 +417,7 @@ class DropDownList<
418417
}
419418

420419
_displayValue(item: Item): string {
421-
// @ts-expect-error refactor DataExpressionMixin
420+
// @ts-expect-error DataExpressionMixin must be typed
422421
return this._displayGetter(item) as string;
423422
}
424423

@@ -695,7 +694,6 @@ class DropDownList<
695694
): void;
696695
_setListOption(optionName: string, value?: unknown): void;
697696
_setListOption(...args: [string, unknown?]): void {
698-
// @ts-expect-error fix on Widget level
699697
this._setWidgetOption('_list', args);
700698
}
701699

@@ -1014,7 +1012,7 @@ class DropDownList<
10141012

10151013
_setSubmitValue(): void {
10161014
const { value } = this.option();
1017-
// @ts-expect-error refactor DataExpressionMixin
1015+
// @ts-expect-error DataExpressionMixin must be typed
10181016
const submitValue = this._shouldUseDisplayValue(value) ? this._displayGetter(value) : value;
10191017

10201018
this._getSubmitElement().val(submitValue);

packages/devextreme/js/__internal/ui/m_autocomplete.ts

Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,41 @@
1-
import { isCommandKeyPressed } from '@js/common/core/events/utils/index';
2-
import registerComponent from '@js/core/component_registrator';
1+
import registerComponent from '@js/core/component_registrator'; // couldn't change import due to inconsistent typings for registerComponent
2+
import type { dxElementWrapper } from '@js/core/renderer';
33
import $ from '@js/core/renderer';
4-
import { Deferred } from '@js/core/utils/deferred';
5-
import { extend } from '@js/core/utils/extend';
4+
import { Deferred, type DeferredObj } from '@js/core/utils/deferred';
5+
import type { DataSourceOptions } from '@js/data/data_source';
6+
import type { DxEvent, PointerInteractionEvent } from '@js/events/events.types';
67
import type { Properties } from '@js/ui/autocomplete';
8+
import type { ItemClickEvent, PageLoadMode } from '@js/ui/list';
79
import { isDefined } from '@ts/core/utils/m_type';
810
import type { OptionChanged } from '@ts/core/widget/types';
11+
import { isCommandKeyPressed } from '@ts/events/utils/index';
12+
import type { ItemCache } from '@ts/ui/drop_down_editor/drop_down_list';
913
import DropDownList from '@ts/ui/drop_down_editor/drop_down_list';
14+
import type { ValueChangedEvent } from '@ts/ui/editor/editor';
15+
import type { ListBaseProperties } from '@ts/ui/list/list.base';
1016

1117
const AUTOCOMPLETE_CLASS = 'dx-autocomplete';
1218
const AUTOCOMPLETE_POPUP_WRAPPER_CLASS = 'dx-autocomplete-popup-wrapper';
1319

14-
export interface AutocompleteProperties extends Omit<Properties, 'onItemClick' | 'onSelectionChanged'> {}
20+
export interface AutocompleteProperties extends Omit<
21+
Properties, 'onItemClick' | 'onSelectionChanged'
22+
> {
23+
24+
}
1525

1626
class Autocomplete extends DropDownList<AutocompleteProperties> {
1727
_supportedKeys(): Record<string, (e: KeyboardEvent) => boolean> {
18-
let item = this._list ? this._list.option('focusedElement') : null;
28+
let item: dxElementWrapper | null = null;
29+
if (this._list) {
30+
const { focusedElement } = this._list.option();
31+
item = focusedElement ? $(focusedElement) : null;
32+
}
1933
const parent = super._supportedKeys();
20-
// @ts-expect-error ts-error
21-
item = item && $(item);
2234

2335
return {
2436
...parent,
2537
upArrow(e): boolean {
26-
// @ts-expect-error ts-error
27-
if (parent.upArrow.apply(this, arguments) && !isCommandKeyPressed(e)) {
38+
if (parent.upArrow.call(this, e) && !isCommandKeyPressed(e)) {
2839
e.preventDefault();
2940
e.stopPropagation();
3041
if (item && !this._calcNextItem(-1)) {
@@ -35,8 +46,7 @@ class Autocomplete extends DropDownList<AutocompleteProperties> {
3546
return true;
3647
},
3748
downArrow(e): boolean {
38-
// @ts-expect-error ts-error
39-
if (parent.downArrow.apply(this, arguments) && !isCommandKeyPressed(e)) {
49+
if (parent.downArrow.call(this, e) && !isCommandKeyPressed(e)) {
4050
e.preventDefault();
4151
e.stopPropagation();
4252
if (item && !this._calcNextItem(1)) {
@@ -54,7 +64,7 @@ class Autocomplete extends DropDownList<AutocompleteProperties> {
5464
if (opened) {
5565
e.preventDefault();
5666
}
57-
return opened;
67+
return Boolean(opened);
5868
},
5969
};
6070
}
@@ -78,17 +88,19 @@ class Autocomplete extends DropDownList<AutocompleteProperties> {
7888
_getAriaAutocomplete(): string {
7989
const { disabled, readOnly } = this.option();
8090

91+
// `||` is required here — `??` would ignore `disabled` when `readOnly` is `false`
8192
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
8293
const isInputEditable = !(readOnly || disabled);
8394

8495
return isInputEditable ? 'list' : 'none';
8596
}
8697

87-
_displayGetterExpr() {
88-
return this.option('valueExpr');
98+
_displayGetterExpr(): undefined | string | ((item: unknown) => string | number | boolean) {
99+
const { valueExpr } = this.option();
100+
return valueExpr;
89101
}
90102

91-
_closeOutsideDropDownHandler({ target }): boolean {
103+
_closeOutsideDropDownHandler({ target }: DxEvent<PointerInteractionEvent>): boolean {
92104
return !$(target).closest(this.$element()).length;
93105
}
94106

@@ -103,18 +115,19 @@ class Autocomplete extends DropDownList<AutocompleteProperties> {
103115
return `${super._popupWrapperClass()} ${AUTOCOMPLETE_POPUP_WRAPPER_CLASS}`;
104116
}
105117

106-
_listConfig() {
107-
return extend(super._listConfig(), {
108-
pageLoadMode: 'none',
109-
onSelectionChanged: (e) => {
118+
_listConfig(): ListBaseProperties {
119+
return {
120+
...super._listConfig(),
121+
pageLoadMode: 'none' as PageLoadMode,
122+
onSelectionChanged: (e): void => {
110123
this._setSelectedItem(e.addedItems[0]);
111124
},
112-
});
125+
};
113126
}
114127

115-
_listItemClickHandler(e) {
128+
_listItemClickHandler(e: ItemClickEvent): void {
116129
this._saveValueChangeEvent(e.event);
117-
// @ts-expect-error ts-error
130+
// @ts-expect-error DataExpressionMixin must be typed
118131
const value = this._displayGetter(e.itemData);
119132
this.option('value', value);
120133
this.close();
@@ -129,28 +142,33 @@ class Autocomplete extends DropDownList<AutocompleteProperties> {
129142
super._setListDataSource();
130143
}
131144

132-
_refreshSelected(): void {}
145+
_refreshSelected(): void {
146+
// Autocomplete has no persistent selection state — suppress parent behavior
147+
// _refreshSelected is called in parent, so we need to override here
148+
// hence we don't need this functionality in Autocomplete
149+
}
133150

134151
_searchCanceled(): void {
135152
super._searchCanceled();
136153
this.close();
137154
}
138155

139-
_loadItem(value, cache) {
156+
_loadItem(value: unknown, cache?: ItemCache): DeferredObj<unknown> {
140157
const selectedItem = this._getItemFromPlain(value, cache);
141158

142-
return Deferred().resolve(selectedItem).promise();
159+
// @ts-expect-error DefferedObj typings and refactor
160+
return Deferred().resolve(selectedItem as unknown).promise();
143161
}
144162

145-
_dataSourceOptions() {
163+
_dataSourceOptions(): DataSourceOptions {
146164
const { maxItemCount } = this.option();
147165
return {
148166
paginate: true,
149167
pageSize: maxItemCount,
150168
};
151169
}
152170

153-
_searchDataSource(searchValue): void {
171+
_searchDataSource(searchValue: string): void {
154172
const { maxItemCount } = this.option();
155173
if (isDefined(maxItemCount)) {
156174
this._dataSource.pageSize(maxItemCount);
@@ -166,12 +184,11 @@ class Autocomplete extends DropDownList<AutocompleteProperties> {
166184
}
167185
}
168186

169-
// eslint-disable-next-line class-methods-use-this
170187
_renderValueEventName(): string {
171188
return 'input keyup';
172189
}
173190

174-
_valueChangeEventHandler(e): void {
191+
_valueChangeEventHandler(e: ValueChangedEvent): void {
175192
const value = this._input().val() || null;
176193
return super._valueChangeEventHandler(e, value);
177194
}
@@ -184,11 +201,10 @@ class Autocomplete extends DropDownList<AutocompleteProperties> {
184201
this._setDefaultAria();
185202
break;
186203
case 'maxItemCount':
187-
// @ts-expect-error ts-error
188-
this._searchDataSource();
204+
this._searchDataSource(this._searchValue());
189205
break;
190206
case 'valueExpr':
191-
// @ts-expect-error ts-error
207+
// @ts-expect-error DataExpressionMixin must be typed
192208
this._compileDisplayGetter();
193209
this._setListOption('displayExpr', this._displayGetterExpr());
194210
super._optionChanged(args);

0 commit comments

Comments
 (0)