-
Notifications
You must be signed in to change notification settings - Fork 214
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Add support for composed types in Typescript #4602
Conversation
@rkodev Please also remember to refactor the composed type which comprises of primitive values only, then if the composed type field is property inside another object the existing logic will handle it e.g:
|
@koros there are a number of changes that have been made For serializing this is the syntax to check for types when its a collection or single value of primitives switch (true) {
case typeof bank_account.account === "string":
writer.writeStringValue("account", bank_account.account as string);
break;
case Array.isArray(bank_account.account) && bank_account.account.every(item => typeof item === 'number'):
writer.writeCollectionOfPrimitiveValues<string>("account", bank_account.account);
break;
default:
writer.writeObjectValue<Account>("account", bank_account.account as Account | undefined | null, serializeBank_account_account);
break;
} as for the deserializing, here is an example of a composed type that will serialize objects / collection of objects or primitives petGetResponse.data = n.getObjectValue<Cat | Dog>(createpetResponseFromDiscriminatorValue) ?? n.getCollectionOfObjectValues<Dog>(createDogFromDiscriminatorValue) ?? n.getNumberValue() ?? n.getStringValue() |
@rkodev can you also look at the defects reported here (ignore the complexity ones) and address the ones you can before I give it another review please? https://sonarcloud.io/project/issues?id=microsoft_kiota&pullRequest=4602&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @rkodev @koros @andrueastman and others for the long haul here!!!!
Please make sure we squash merge this PR as there's a lot of convoluted history.
🚀 🚢
@andrueastman FYI you still have two comments that are unresolved in the history. I didn't resolve them so you get a chance at checking whether they still apply |
Quality Gate passedIssues Measures |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@andrueastman FYI you still have two comments that are unresolved in the history. I didn't resolve them so you get a chance at checking whether they still apply
Confirmed these are resolved. Thanks for pushing this through @koros @rkodev
@rkodev I just noticed we forgot the changelog entry. Can you stand a quick pr please? |
Done |
Fixes: #1812
Related Tickets
TODO
Generation Logic Design:
1. Composed Types Comprised of Primitives Without Discriminator Property
Sample yml
For the union of primitive values shown above, the generation logic is as follows:
The factory method for union of primitives determines the return type from the parse node value. For example, if the node is
number | string
, the method should return the correct type based on the node's value, as shown below:There is no need for a deserialization method, so it is omitted during generation.
The serialization method will determine the type of the node and call the respective method on the abstraction library for that type. Using the example above, if the node is number | string, the serializer should call either
writer.writeNumberValue
orwriter.writeStringValue
based on the node's actual value, as shown below:2. Composed Types Comprised of Objects with a Discriminator Property Specified
Sample yml
For the example above, the factory method determines which pet to create, either
Cat
orDog
, based on the discriminator information, as shown below:The deserializer is not necessary since the function has been delegated to the respective handlers as shown above. So instead of
deserializePet
, we have eitherdeserializeCat
if the response is aCat
, ordeserializeDog
if the response is aDog
.The serializer will also delegate the writing functionality to the respective writer. In the example above, the generated output will be as follows:
When there is no discriminator property specified, the serialization logic should default to serializing all possible types. This approach ensures that the writer captures all available fields from each type. For example, in the following TypeScript code, the absence of a discriminator property leads to serializing both Cat and Dog fields in the PetGetResponse:
3. Intersection of Object Values
Edge Cases
Union between objects and primitive values with no discriminator property specified