delegateas / XrmDefinitelyTyped

Tool to generate TypeScript declaration files for Dynamics 365/CDS client-side coding.
http://delegateas.github.io/Delegate.XrmDefinitelyTyped/
MIT License
133 stars 53 forks source link

TypeScript 2.6 does not work with XrmQuery #33

Closed henrikhannemose closed 6 years ago

henrikhannemose commented 7 years ago

When using TypeScript 2.6, there appears to be an issue with (at least) retrieveMultiple.

Running the example of retrieveMultiple from the wiki, we get an error since we cannot filter on an empty object:

RetrieveMultiple, empty object

The entire definition for retrieveMultiple appears to be broken (XrmQuery.retrieveMultiple<Account_Select, {}, {}, {}, {}, {}>(...)) XrmQuery.retrieveMultiple

What has changed with TypeScript 2.6 (I have not tested with TypeScript 2.5 to see if that works or not), and what can we do to make XrmQuery work?

zaha commented 6 years ago

I experience the same issue using Typescript 2.6.1

TomMalow commented 6 years ago

I have a potential solution. XDT generates an interface WebEntities for each entity. This interface holds a single intersection type for the interface which is an intersection of:

However, we are never using more than one of these type in our method calls. The retrieve / retrieveMultiple call always uses WebEntities as a WebMappingRetrieve interface. The update call uses it as the WebMappingCUD interface. So there are no reason why WebEntities should have an intersection type other than reduce to the amount of interfaces that the definition holds. My proposal is then to change

interface WebEntities {
  accounts: WebMappingRetrieve<Account_Select,Account_Expand,Account_Filter,Account_Fixed,Account_Result,Account_FormattedResult> & WebMappingCUD<Account_Create,Account_Update> & WebMappingRelated<Account_RelatedOne,Account_RelatedMany>;
}

to the following

interface WebEntitiesRetrieve {
  accounts: WebMappingRetrieve<Account_Select,Account_Expand,Account_Filter,Account_Fixed,Account_Result,Account_FormattedResult>;
}

interface WebEntitiesRelated {
    accounts: WebMappingRelated<Account_RelatedOne, Account_RelatedMany>;
}

interface WebEntitiesCUD {
    accounts: WebMappingCUD<Account_Create, Account_Update>;
}

for each entity. The method calls then needs to be changed to expect one of the three interfaces. So the retrieve:

function retrieve<ISelect, IExpand, IFixed, FormattedResult, Result>(entityPicker: (x: WebEntities) => WebMappingRetrieve<ISelect, IExpand, any, IFixed, Result, FormattedResult>, id: string): XQW.RetrieveRecord<ISelect, IExpand, IFixed, FormattedResult, Result>;

Would be changed to

function retrieve<ISelect, IExpand, IFixed, FormattedResult, Result>(entityPicker: (x: WebEntitiesRetrieve) => WebMappingRetrieve<ISelect, IExpand, any, IFixed, Result, FormattedResult>, id: string): XQW.RetrieveRecord<ISelect, IExpand, IFixed, FormattedResult, Result>;

This proposal all hangs on my assumption that the WebEntities interface is always reduced down to on of the three types in all of the method calls. But from my limited testing it seems to work.

I think, and this is just a guess, that the previous code was "incorrect" from the start but TypeScript simply did not have proper checking on intersection types. This was then fixed in 2.6