DevExtreme icon indicating copy to clipboard operation
DevExtreme copied to clipboard

Internal Types

Open IlyaKhD opened this issue 3 years ago • 163 comments

The Problem

We're extending the DevExtreme TypeScript API and adding a lot of new types. To maintain consistency, we are reviewing existing type names and locations. At the same time, we're separating public types from internal ones to protect you from unnecessary breaking changes in the future.

The Solution

We marked a lot of types as deprecated with the following message:

Warning! This type is used for internal purposes. Do not import it directly.

This means that the type is considered to be internal. In some cases, it will be renamed or moved to another module.

We Need Your Feedback

We really need your feedback. If you see that warning message, please specify the type that cause it. We will offer you a suitable replacement.

IlyaKhD avatar Jun 11 '21 13:06 IlyaKhD

Which version of DevExtreme has these changes?

hakimio avatar Jun 14 '21 07:06 hakimio

We added the @deprecated tag to these warnings in v21.1. After the upgrade, you can check your console and report to us which types are causing it.

IlyaKhD avatar Jun 17 '21 08:06 IlyaKhD

I'm currently développions an Angular + .NET5 solution with DevExtreme 21.2.3 version and I'm finding @deprecated attribute with most of the interface/event/class types that I need to used in my code. I really want to fully use the typing features with intellisense with vscode and angular because I think it's more easy to code and make code expectation more obvious.

I would like to be sure that I can still use the typing with DevExtreme so ti will be appreciated if you can provide a working typing file without @deprecated. Thanks!

For example, I cannot use the LoadOptions:

const customStore = new CustomStore({
     load: (loadOptions: DevExpress.data.LoadOptions) => {

If I go to definition to the LoadOptions, this is what I found:

/**
 * 
 * @deprecated Warning! This type is used for internal purposes. Do not import it directly.
 */
export interface LoadOptions {

SteveLemire avatar Jun 21 '21 12:06 SteveLemire

@SteveLemire, could you give us a complete list of these warnings? It would be helpful if you share a log file. We'll review the types you're using and mark them as public or specify recommended replacements.

IlyaKhD avatar Jun 23 '21 13:06 IlyaKhD

@IlyaKhD here is a list of DX deprecated types we have used:

import {isObject} from 'devextreme/core/utils/type';
import {CustomStoreOptions} from 'devextreme/data/custom_store';
import {dxDataGridRowObject} from 'devextreme/ui/data_grid';
import {LoadOptions} from 'devextreme/data/load_options';
import {dxValidatorResult} from 'devextreme/ui/validator';
import {DataSourceOptions} from 'devextreme/data/data_source';
import dxButtonGroupItem = DevExpress.ui.dxButtonGroupItem;
import {dxTextBoxOptions} from 'devextreme/ui/text_box';
import {dxSelectBoxOptions} from 'devextreme/ui/select_box';
import {dxDataGridOptions} from 'devextreme/ui/data_grid';
import {dxGalleryOptions} from 'devextreme/ui/gallery';
import {dxFormOptions} from 'devextreme/ui/form';
import positionConfig = DevExpress.positionConfig;
import devices, {Device} from 'devextreme/core/devices';

Following is not marked as deprecated but you might have forgotten about it:

import {humanize} from 'devextreme/core/utils/inflector';

hakimio avatar Jun 24 '21 10:06 hakimio

@SteveLemire, could you give us a complete list of these warnings? It would be helpful if you share a log file. We'll review the types you're using and mark them as public or specify recommended replacements.

@hakimio mentioned most of them.

Im starting the project so I don't have the complete list. I'm coding generic component and they are all auto-generated so most of the code to render devextreme components is done in the code behind and then bind to the html component declaration.

When I use a new devextreme component, I would like to have typing for events, configuration, datasource and other related types to manage the rendering from the code behind.

SteveLemire avatar Jun 24 '21 15:06 SteveLemire

@IlyaKhD I understand and fully agree that some internal library logic should be kept private, but coming from Sencha ExtJS framework, one thing I miss is a large amount of utility classes available to the user of the framework. Basically, there was almost no reason to install any 3rd party utility library since you already had everything you needed. I think, it might be best that instead of trying to hide as much as you can, you would also consider making public at least some of the DX utility functions you consider stable. If you would add them to your API documentation with some example usage, it would add a lot of value to DX users.

hakimio avatar Jun 25 '21 11:06 hakimio

@IlyaKhD, hi!

We're using ColumnCustomizeTextArg type and it's deprecated now. We're using it for customizeText function

Bykiev avatar Jun 29 '21 12:06 Bykiev

@hakimio, I think these two options are not exclusive. I mean hiding internal types that are used in Components' property declarations and making utilities public.

We're reviewing internal types to improve the component configuration process, but we're not changing the API. In a general case, no runtime features are made public or private.

Making internal utilities public is a matter of extending the API, not just changing types.

IlyaKhD avatar Jun 29 '21 15:06 IlyaKhD

@SteveLemire, @hakimio, @Bykiev thank you for sharing these types lists. Once we have any updates we'll post them here.

Btw, the 21.1.4 update includes a couple of public replacements:

  • dxDataGrid
    • Column instead of dxDataGridColumn
    • ColumnButton instead of dxDataGridColumnButton
  • dxTreeList
    • Column instead of dxDataGridColumn
    • ColumnButton instead of dxDataGridColumnButton
  • dxScheduler
    • Appointment instead of dxSchedulerAppointment

IlyaKhD avatar Jun 29 '21 15:06 IlyaKhD

@IlyaKhD, can you please help me with DevExtreme typings?

I'm using dxTextArea onKeyDown event, it's type is NativeEventInfo<T> (NativeEventInfo<dxTextArea> in my case). I would like to check wich key was pressed, but how to get access to JQuery keyCode from DX EventObject?

Bykiev avatar Jun 30 '21 11:06 Bykiev

Also Deffered is marked as internal, but is used for custom adapter implementation here

allowEditing (as function) and other type definitions is hard to use


    /**
     * Specifies whether a user can delete rows. It is called for each data row when defined as a function.
     */
    allowDeleting?:
      | boolean
      | ((options: { component?: dxDataGrid; row?: RowObject }) => boolean);

RowObject type is internal, it'll be better to create EditingObject interface with component and row props

Same here with visible (as function) and many other types where RowObject is used

Bykiev avatar Jun 30 '21 15:06 Bykiev

import PivotGridDataSource, { PivotGridDataSourceOptions } from 'devextreme/ui/pivot_grid/data_source';

const pivotGridDataSourceOptions: PivotGridDataSourceOptions = {
        fields: [{
          caption: 'Status',
          dataField: 'status',
          area: 'row',
          //sortBySummaryField: 'Total'
        }, {
          caption: 'DNSP',
          dataField: 'dnsp',
          area: 'column'
        }, {
            caption: 'Total',
            dataField: 'deviceId',
            dataType: 'string',
            summaryType: 'count',
            area: 'data'
        }],
        store: dummyStore
};
    
const dataSource: PivotGridDataSource = new PivotGridDataSource(pivotGridDataSourceOptions);

iofluxdev1 avatar Jul 02 '21 00:07 iofluxdev1

Maybe I am missing something out, but we are using the options (like DevExpress.ui.dxTagBoxOptions) on multiple occasions, e.g. when using TypeMoq for testing:

jQueryMock.verify((mock) => mock.dxTagBox(
        TypeMoq.It.is<DevExpress.ui.dxTagBoxOptions>((options) => {
            return options.showClearButton === true && options.displayExpr === 'displayValue';
        })
), TypeMoq.Times.once());

Is there any way to use this typings in a non-deprecated way? Would I need to use DevExpress.ui.dxTagBox.Properties instead?

Owlbertz avatar Jul 06 '21 10:07 Owlbertz

Hi @Bykiev, @iofluxdev1, @Owlbertz,

First of all, I want to thank you for sharing your usage scenarios. This will help us to make our TypeScript definitions better.

As for the questions, let me address them one by one.

@Bykiev

I'm using dxTextArea onKeyDown event, it's type is NativeEventInfo<T> (NativeEventInfo<dxTextArea> in my case). I would like to check wich key was pressed, but how to get access to JQuery keyCode from DX EventObject?

As far as I understand, you are using Angular If you are using a native event, it is unnecessary to get access to the jQuery keyCode. You can use a native keyCode option. However, if your usage scenario is different, I would appreciate it if you describe it and the issue in greater detail.

@Owlbertz

Is there any way to use this typings in a non-deprecated way? Would I need to use DevExpress.ui.dxTagBox.Properties instead?

Currently, we are working on a list of updated typings, but it is not ready yet. So, you can continue using deprecated options. Once updated options are ready, we will publish them and update deprecation messages.

LexDX avatar Jul 08 '21 17:07 LexDX

I'm using dxTextArea onKeyDown event, it's type is NativeEventInfo (NativeEventInfo in my case). I would like to check wich key was pressed, but how to get access to JQuery keyCode from DX EventObject?

As far as I understand, you are using Angular If you are using a native event, it is unnecessary to get access to the jQuery keyCode. You can use a native keyCode option. However, if your usage scenario is different, I would appreciate it if you describe it and the issue in greater detail.

@LexDX, thank you for you time and efforts! Do I understand you correctly that I should cast event property of dxTextArea onValueChanged event to KeyboardEvent or jQuery.Event (if jQuery is used)?

It's not clear for me, as it's defined in DevExtreme typings as DxEvent which extends EventType or EventObject.

Upd: I can't cast it directly neither to KeyboardEvent nor jQuery.Event.

Upd2 It seems event typings are wrong, EventType should extend JQueryEventObject:

  interface EventType extends JQueryEventObject {
    cancel?: boolean;
  }

I did a PR #18265 for this

Thanks!

Bykiev avatar Jul 08 '21 19:07 Bykiev

Some 'deprecated' imports from me:

import dxScrollable from 'devextreme/ui/scroll_view/ui.scrollable'

dxScrollable.defaultOptions({ // `dxScrollable` marked as deprecated
  ...
})

import type { PivotGridDataSourceField } from 'devextreme/ui/pivot_grid/data_source'

I use this type for typing fields in PivotGrid.


import type { dxPivotGridPivotGridCell } from 'devextreme/ui/pivot_grid'

I use this type for getting information about the pivot grid cell (for example in functions called inside onCellPrepared).


import type { ExcelDataGridCell } from 'devextreme/excel_exporter'
import type { ExcelPivotGridCell } from 'devextreme/excel_exporter'

Used in customizeCell callbacks in custom export.


import type { DeferredObj } from 'devextreme/core/utils/deferred'
...
const tabPanel = tabPanelRef.current?.instance
const deferredItems: DeferredObj<unknown>[] = (tabPanel as any)?._deferredItems ?? []
await Promise.all(deferredItems.map((deferredItem) => deferredItem.resolve()))

In some cases (before export for example) I need preload tab contents.

Semigradsky avatar Jul 11 '21 16:07 Semigradsky

As I wrote in my post earlier, I'm generating grid and form in the code-behind. During this process, I have to create form items but there is no "form item types" so I had to create dxFormItemTypes and dxFormSimpleItemEditorTypes like this:

import {
  dxFormButtonItem,
  dxFormEmptyItem,
  dxFormGroupItem,
  dxFormSimpleItem,
  dxFormTabbedItem,
} from 'devextreme/ui/form';

export type dxFormItemTypes =
  | dxFormSimpleItem
  | dxFormGroupItem
  | dxFormTabbedItem
  | dxFormEmptyItem
  | dxFormButtonItem;

export type dxFormSimpleItemEditorTypes =
  | 'dxAutocomplete'
  | 'dxCalendar'
  | 'dxCheckBox'
  | 'dxColorBox'
  | 'dxDateBox'
  | 'dxDropDownBox'
  | 'dxHtmlEditor'
  | 'dxLookup'
  | 'dxNumberBox'
  | 'dxRadioGroup'
  | 'dxRangeSlider'
  | 'dxSelectBox'
  | 'dxSlider'
  | 'dxSwitch'
  | 'dxTagBox'
  | 'dxTextArea'
  | 'dxTextBox';

I'm wondering why these "types" are not available from Devexpress library?

SteveLemire avatar Jul 12 '21 11:07 SteveLemire

Why is this deprecated?

export interface RemoteFileSystemProviderOptions extends FileSystemProviderBaseOptions<RemoteFileSystemProvider> {
    /**
     * Specifies a function that customizes an Ajax request before it is sent to the server.
     */
    beforeAjaxSend?: ((options: { headers?: any, xhrFields?: any, formData?: any }) => void);
    /**
     * Specifies a function that customizes a form submit request before it is sent to the server.
     */
    beforeSubmit?: ((options: { formData?: any }) => void);
    /**
     * Specifies the URL of an endpoint used to access and modify a file system located on the server.
     */
    endpointUrl?: string;
    /**
     * Specifies which data field provides information about whether a directory has subdirectories.
     */
    hasSubDirectoriesExpr?: string | Function;
    /**
     * Specifies the request headers.
     */
    requestHeaders?: any;
}

I'm also having problems with requestHeaders, once specified a few default headers are no longer sent (e.g.: Origin which is used by CORS).

R4DIC4L avatar Jul 13 '21 07:07 R4DIC4L

Hi, guys. Tell me please, what I can use instead of import { Summary } from 'devextreme/ui/data_grid' ?

AChelp avatar Jul 13 '21 12:07 AChelp

Hi @all,

Thank you for your continuous feedback.

@Bykiev,

Yes, I see the issue now. We did not include the native event in Angular typings. So, there is no way to use this event in the current version. As a temporary workaround, you can cast the e.event object to any. Then, use originalEvent and cast it to KeyboardEvent:

const evt = (e.event as any).originalEvent as KeyboardEvent;

Regarding your pull request, let me share more information about our TypeScript changes. We do not have plans to make the same jQuery typings for all frameworks. Our main goal is to create a set of typings that will be useful in the current framework. So, we did not include jQuery typings by default. However, the lack of native events causes issues, so we will discuss adding the missing options.

@Semigradsky, thank you for sharing your typings.

@SteveLemire,

We just started extending our typings and rewriting our TypeScript definitions. The work is not finished yet, so you can expect changes in next releases. We will take your usage scenario into account.

@R4DIC4L,

We deprecated all TypeScript definitions as we did not have any public types yet. In this GitHub issue, we collect main use cases so that we can update our typings and make them public later.

Regarding the issue with request headers, please submit a ticket to our Support Center - https://www.devexpress.com/ask. In the ticket, please share more details and a sample project. Our team will analyze and debug it. This will help us find a precise solution for you.

@AChelp,

Currently, we do not have an alternative. Once we add it, we will update deprecation messages with the required information so that you will be able to migrate to correct typings.

LexDX avatar Jul 14 '21 15:07 LexDX

@LexDX, thank you for your comments! But I still don't understand the puprpose of extending DxEvent with an EventType interface, which extends empty interface JQueryEventObject, also there is a comment here:

/**
 * @docid
 * @type EventObject|jQuery.Event
 */

So, DxEvent should extend EventObject or jQuery.Event (if jQuery is used) or JQueryEventObject should extend jQuery.Event

There is some more issues with two-way binding in Angular, I've already described it here

Bykiev avatar Jul 14 '21 16:07 Bykiev

Thanks @LexDX to give us all these feedbacks, it's really appreciated.

Devextreme is a very nice productivity components framework and I want to use the Type script features in the frontend the same way I do in the backend C# .net5 server.

Instead of anonymous typing (like javascript), I want to use typing as much as I can so all developers are aware of the in/out properties/methods. As you know, the latest version of typescript is becoming more strict for all theses reasons. That's the main purpose of using TypeScript!!!

Maybe I'm wrong by generating UI/UX in the code behind but I think it's best way to get the power of customizations with my code that creates responsive grids and forms.

By the way, I just bought your latest Devetreme version 21.1.4 and upgraded to latest Angular 12.1.1 and everything works fine so nice job to all your teams!!!!

Thanks again!!

SteveLemire avatar Jul 15 '21 18:07 SteveLemire

dxToolbarItem

https://js.devexpress.com/Documentation/ApiReference/UI_Components/dxToolbar/Configuration/items/ image

Can we get everything in your documentation that refers to a type to be available? Ideally if you can keep the names referred to your documentation to avoid us having a considerable amount of tech debt across our apps would be appreciated.

mtopp7 avatar Jul 19 '21 09:07 mtopp7

Hi @all,

@Bykiev,

But I still don't understand the purpose of extending DxEvent with an EventType interface, which extends empty interface JQueryEventObject

We use the built-in jQuery JQueryEventObject when jQuery is enabled in the application. For the situation when there is no jQuery in the application, we use an empty interface to avoid compilation issues.

So, DxEvent should extend EventObject or jQuery.Event (if jQuery is used) or JQueryEventObject should extend jQuery.Event

The main reason why our event types are created in this way is related to the fact that not all applications have jQuery integration. So, to avoid creating two sets of typings, we used a different solution. However, the documentation shows the information about real event types.

There is some more issues with two-way binding in Angular, I've already described it here

Thank you for the information. I'll check the issue and reply to you in the initial thread once I have any news.

@SteveLemire,

Thank you for the detailed explanation. I think I got your point and I shared it with our team.

@mtopp7,

We have plans to update our documentation once we finish our new typings. So, we'll make these new TypeScript definitions public and documented.

LexDX avatar Jul 20 '21 22:07 LexDX

import { dxTabPanelItem } from 'devextreme/ui/tab_panel';

dxTabPanelItem marked as deprecated, used as a dataSource for tabPanel control

Bykiev avatar Jul 22 '21 07:07 Bykiev

We are using dxForm*Item (e.g. dxFormSimpleItem) to create form items in separate locations from where they are actually added to the form.

dominic-simplan avatar Jul 22 '21 12:07 dominic-simplan

I want to iterate over all visible rows of my TreeList when the drag starts: image How can I do that in a strongly typed manner?

davidich avatar Jul 23 '21 22:07 davidich

@davidich they have deprecated everything but haven't introduced replacements yet...

hakimio avatar Jul 24 '21 21:07 hakimio

I am currently using this: import { dxDataGridSelection, dxDataGridScrolling } from 'devextreme/ui/data_grid';

I am using a custom control to deal with selection of rows, and I need the type to be able to pass the selection props that were supplied to the grid down to my custom component.

Similar reasons for the dxDataGridScrolling also, I need to pass the prop values around and need the type.

FBNitro avatar Jul 29 '21 17:07 FBNitro