Skip to content

Commit 31fa3bf

Browse files
Base components: improve TS typing (DevExpress#30652)
1 parent fe43490 commit 31fa3bf

File tree

86 files changed

+742
-570
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+742
-570
lines changed

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

Lines changed: 74 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,16 @@ import { Options } from '@js/core/options/index';
1212
import type { DefaultOptionsRule } from '@js/core/options/utils';
1313
import { convertRulesToOptions } from '@js/core/options/utils';
1414
import { PostponedOperations } from '@js/core/postponed_operations';
15-
import type { dxElementWrapper } from '@js/core/renderer';
1615
import Callbacks from '@js/core/utils/callbacks';
1716
import { noop } from '@js/core/utils/common';
1817
import { getPathParts } from '@js/core/utils/data';
1918
import { extend } from '@js/core/utils/extend';
2019
import { name as publicComponentName } from '@js/core/utils/public_component';
21-
import { isDefined, isFunction, isPlainObject } from '@js/core/utils/type';
22-
import type { EventInfo, InitializedEventInfo } from '@js/events';
23-
24-
import type { OptionChanged } from './types';
20+
import {
21+
isDefined, isFunction, isPlainObject, isString,
22+
} from '@js/core/utils/type';
23+
import type { DxEvent, EventInfo, InitializedEventInfo } from '@js/events';
24+
import type { OptionChanged } from '@ts/core/widget/types';
2525

2626
const getEventName = (
2727
actionName: string,
@@ -40,20 +40,44 @@ export interface ActionConfig {
4040
category?: 'rendering';
4141
}
4242

43-
export interface Properties<TComponent> extends ComponentOptions<
43+
export interface DefaultActionConfig<TComponent> {
44+
component: TComponent;
45+
context?: TComponent;
46+
}
47+
48+
export interface DefaultActionArgs<TComponent> {
49+
component: TComponent;
50+
element?: Element;
51+
event?: DxEvent;
52+
model?: unknown;
53+
}
54+
55+
export interface ComponentProperties<TComponent> extends ComponentOptions<
4456
EventInfo<TComponent>,
4557
InitializedEventInfo<TComponent>,
4658
OptionChangedEventInfo<TComponent>
4759
> {
48-
onInitializing?: ((e: Record<string, unknown>) => void) | undefined;
60+
onInitializing?: ((e: [ComponentProperties<TComponent>]) => void) | undefined;
4961

5062
// eslint-disable-next-line @typescript-eslint/no-explicit-any
5163
defaultOptionsRules?: DefaultOptionsRule<any>[];
64+
65+
beforeActionExecute?: (
66+
component: TComponent,
67+
action: (e) => void,
68+
config: ActionConfig,
69+
) => (args) => void;
70+
71+
onActionCreated?: (
72+
component: TComponent,
73+
action: (e) => void,
74+
config: ActionConfig
75+
) => () => unknown;
5276
}
5377

5478
export class Component<
5579
TComponent extends Component<TComponent, TProperties>,
56-
TProperties extends Properties<TComponent> = Properties<TComponent>,
80+
TProperties extends ComponentProperties<TComponent> = ComponentProperties<TComponent>,
5781
// @ts-expect-error dxClass inheritance issue
5882
> extends (Class.inherit({}) as new() => {}) implements PublicComponent<TProperties> {
5983
_deprecatedOptions!: Partial<TProperties>;
@@ -162,7 +186,6 @@ export class Component<
162186
);
163187

164188
this._options.onChanging(
165-
166189
(name, previousValue, value) => this._initialized
167190
&& this._optionChanging(name, previousValue, value),
168191
);
@@ -175,7 +198,7 @@ export class Component<
175198
this._options.onStartChange(() => this.beginUpdate());
176199
this._options.onEndChange(() => this.endUpdate());
177200
this._options.addRules(this._defaultOptionsRules());
178-
this._options.validateOptions((o) => this._validateOptions(o));
201+
this._options.validateOptions((opts: TProperties) => this._validateOptions(opts));
179202

180203
if (options && options.onInitializing) {
181204
// @ts-expect-error
@@ -214,11 +237,15 @@ export class Component<
214237
}
215238

216239
_createOptionChangedAction(): void {
217-
this._optionChangedAction = this._createActionByOption('onOptionChanged', { excludeValidators: ['disabled', 'readOnly'] });
240+
this._optionChangedAction = this._createActionByOption('onOptionChanged', {
241+
excludeValidators: ['disabled', 'readOnly'],
242+
});
218243
}
219244

220245
_createDisposingAction(): void {
221-
this._disposingAction = this._createActionByOption('onDisposing', { excludeValidators: ['disabled', 'readOnly'] });
246+
this._disposingAction = this._createActionByOption('onDisposing', {
247+
excludeValidators: ['disabled', 'readOnly'],
248+
});
222249
}
223250

224251
_optionChanged(args: OptionChanged<TProperties> | Record<string, unknown>): void {
@@ -248,8 +275,7 @@ export class Component<
248275
}
249276

250277
_lockUpdate(): void {
251-
// eslint-disable-next-line no-plusplus
252-
this._updateLockCount++;
278+
this._updateLockCount += 1;
253279
}
254280

255281
_unlockUpdate(): void {
@@ -304,17 +330,16 @@ export class Component<
304330
this._isUpdateAllowed() && this._commitUpdate();
305331
}
306332

307-
// eslint-disable-next-line @stylistic/max-len
308-
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/explicit-function-return-type, @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
309-
_optionChanging(...args: any[]) {
333+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
334+
_optionChanging(...args: any[]): void {
310335

311336
}
312337

313338
_notifyOptionChanged(option: string, value: unknown, previousValue: unknown): void {
314339
if (this._initialized) {
315340
const optionNames = [option].concat(this._options.getAliasesByName(option));
316-
// eslint-disable-next-line @typescript-eslint/prefer-for-of, no-plusplus
317-
for (let i = 0; i < optionNames.length; i++) {
341+
// eslint-disable-next-line @typescript-eslint/prefer-for-of
342+
for (let i = 0; i < optionNames.length; i += 1) {
318343
const name = optionNames[i];
319344
const args = {
320345
name: getPathParts(name)[0],
@@ -340,14 +365,14 @@ export class Component<
340365
return this._options.initial(name);
341366
}
342367

343-
_defaultActionConfig(): { context: TComponent; component: TComponent } {
368+
_defaultActionConfig(): DefaultActionConfig<TComponent> {
344369
return {
345370
context: this as unknown as TComponent,
346371
component: this as unknown as TComponent,
347372
};
348373
}
349374

350-
_defaultActionArgs(): { component: TComponent; element?: dxElementWrapper; model?: unknown } {
375+
_defaultActionArgs(): DefaultActionArgs<TComponent> {
351376
return {
352377
component: this as unknown as TComponent,
353378
};
@@ -376,7 +401,7 @@ export class Component<
376401
}
377402

378403
_createActionByOption(
379-
optionName: string,
404+
optionName: keyof TProperties,
380405
config?: ActionConfig,
381406
): (event?: unknown) => void {
382407
// eslint-disable-next-line @typescript-eslint/init-declarations
@@ -386,14 +411,12 @@ export class Component<
386411
// eslint-disable-next-line @typescript-eslint/init-declarations
387412
let actionFunc;
388413

389-
// eslint-disable-next-line no-param-reassign
390-
config = extend({}, config);
414+
let actionConfig = { ...config ?? {} } ;
391415

392416
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
393417
const result = (...args) => {
394418
if (!eventName) {
395-
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing, no-param-reassign
396-
config = config || {};
419+
actionConfig = actionConfig || {};
397420

398421
if (typeof optionName !== 'string') {
399422
throw errors.Error('E0008');
@@ -411,27 +434,33 @@ export class Component<
411434
actionFunc = this.option(optionName);
412435
}
413436

414-
if (!action && !actionFunc && !config?.beforeExecute
415-
&& !config?.afterExecute && !this._eventsStrategy.hasEvent(eventName)) {
437+
if (!action
438+
&& !actionFunc
439+
&& !actionConfig?.beforeExecute
440+
&& !actionConfig?.afterExecute
441+
&& !this._eventsStrategy.hasEvent(eventName)
442+
) {
416443
return;
417444
}
418445

419446
if (!action) {
420-
// @ts-expect-error
421-
const { beforeExecute } = config;
422-
// @ts-expect-error
423-
config.beforeExecute = (...props): void => {
447+
const { beforeExecute } = actionConfig;
448+
449+
actionConfig.beforeExecute = (...props): void => {
424450
beforeExecute?.apply(this, props);
425451
this._eventsStrategy.fireEvent(eventName, props[0].args);
426452
};
427-
action = this._createAction(actionFunc, config);
453+
action = this._createAction(actionFunc, actionConfig);
428454
}
429455

430456
// @ts-expect-error
431457
if (Config().wrapActionsBeforeExecute) {
432-
const beforeActionExecute = this.option('beforeActionExecute') || noop;
433-
// @ts-expect-error
434-
const wrappedAction = beforeActionExecute(this, action, config) || action;
458+
const { beforeActionExecute = noop } = this.option();
459+
const wrappedAction = beforeActionExecute(
460+
this as unknown as TComponent,
461+
action,
462+
actionConfig,
463+
) || action;
435464
// eslint-disable-next-line consistent-return, @typescript-eslint/no-unsafe-return
436465
return wrappedAction.apply(this, args);
437466
}
@@ -444,11 +473,13 @@ export class Component<
444473
if (Config().wrapActionsBeforeExecute) {
445474
return result;
446475
}
447-
const onActionCreated = this.option('onActionCreated') || noop;
476+
const { onActionCreated = noop } = this.option();
448477

449-
// @ts-expect-error
450-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
451-
return onActionCreated(this, result, config) || result;
478+
return onActionCreated(
479+
this as unknown as TComponent,
480+
result,
481+
actionConfig,
482+
) || result;
452483
}
453484

454485
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
@@ -463,10 +494,10 @@ export class Component<
463494
return this;
464495
}
465496

466-
hasActionSubscription(actionName: string): boolean {
497+
hasActionSubscription(actionName: keyof TProperties): boolean {
467498
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
468499
return !!this._options.silent(actionName)
469-
|| this._eventsStrategy.hasEvent(getEventName(actionName));
500+
|| (isString(actionName) && this._eventsStrategy.hasEvent(getEventName(actionName)));
470501
}
471502

472503
isOptionDeprecated(name: string): boolean {
@@ -481,7 +512,7 @@ export class Component<
481512

482513
// eslint-disable-next-line @stylistic/max-len
483514
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
484-
_getOptionValue(name: string, context?: any): any {
515+
_getOptionValue(name: keyof TProperties, context?: any): any {
485516
const value = this.option(name);
486517

487518
if (isFunction(value)) {

0 commit comments

Comments
 (0)