-
Notifications
You must be signed in to change notification settings - Fork 24
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
First cut at typescript-lite generator implementation. #20
Conversation
Also allow Arrays and Maps of anonymous unions
Made a few changes since first posting:
Going to go ahead and start writing a test-suite now. When that's done I'm going to return to the code and clean it up a bit. |
/** | ||
* Magic eight ball answers. | ||
*/ | ||
export type MagicEightBallAnswer = "IT_IS_CERTAIN" | "ASK_AGAIN_LATER" | "OUTLOOK_NOT_SO_GOOD" ; |
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.
@eboto Sorry, I'm not familiar with the idioms of typescript. Can you provide a rationale for not including UNKNOWN$
in this list?
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.
Sure! We use UNKNOWN$
at runtime in existing client libraries to surface the case when an unknown enum value, probably from a later version of the software, appears down the wire. However, the enums as written here (string-literal types) do not have a run-time component so it would be impossible to coerce that unknown string into UNKNOWN$
as part of the type. So I chose not to include it in the type.
That pretty much leaves it on the client to compare to all the KNOWN enums, and let the unknown one fall off the end. e.g. if you have enum Fruits { APPLE, ORANGE }
then the client would have to do
const fruit: Fruit = /* get the fruit */
if (fruit == Fruit.APPLE) {
// something
} else if (fruit == Fruit.ORANGE) {
// something
} else {
// handle unknown
}
Now thinking about it though, I could provide a utility function like Fruit.isUnknown(enumValue: Fruit)
that returns boolean if we got an unknown value. But I'm not sure how much that would help the experience.
Did that make sense? What do you think?
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.
Looks pretty reasonable. Given that they're represented as strings, it should be reasonable to use them in a switch
statement as well. Having the enum variants generated I think is the right call. I'd expect they'll gzip really well, such that the overhead of including them won't be much higher than having a bunch of string constants in the source code. (And this way, you get autocomplete, and the potential for tooling to better understand what's going on in the future.)
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.
Good point! Don't know why I reached for this gross if-elses first.
I'm going to give the switch usage a workup in the testsuite then update the docs.
According to this typescript issue, we will get compiler warnings future versions for strings that are not in the string literal type...so that will make it even nicer (as long as it doesn't stop you from falling through to default
.
EDIT: Also I think I agree with you about the constants down the wire. I'm going to keep them. =)
Hey @eboto I've taken a super quick look over. I think you're definitely on the right track. I'll try and take the time to give a more thorough review over the next few days. I'm excited to see this come in, and land successfully. Thanks for your great work already! |
I introduced some test cases in the form of an NPM build that processes the reference suite. Though it only tests that the type system accepts correct input now, I would like to additionally put in some tests to that show we don't accept the wrong input. That's a little messier though here because the data's shape is verified at compile time. I do have some outstanding questions relating to testcases that wouldn't pass:
Pending a more thorough review, my only remaining tasks AFAIK on this issue are:
|
Hey @saeta I was writing test-cases trying to use the existing json objects in reference suite, when I came across FortuneCookie.json. I assume it's used as a positive example, but the extra fields "map" and "simple" seem to disqualify it from the courier definition. Any idea why it is included as a positive example? Are supersets of a courier record supposed to be valid examples of the courier record as well? Doesn't have much bearing on typescript-lite bindings anyways but I'm just curious. |
OK I'm done with the reference test suite. Let me know if the suite is up to snuff! |
Alright I'm done here, @saeta ! I'm sure we'll have a handful more patches later on, and I'd love to add a more appropriate formatter, but hey I think this is a decent starting point. May be worth noting that performing |
@@ -1,5 +1,8 @@ | |||
namespace org.coursera.enums | |||
|
|||
/** | |||
* An enum dedicated to the finest of the food groups. |
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.
:-)
Thanks for the review, Brennan! Lots of good food for thought. So summing it all up it seems like these are the remaining issues! Does this sound accurate to you?
|
* Patch mangle escaping to use $ by convention instead of _ * Removed backticks from unionsArray and unionsMap in WithAnonymousUnionArray in the reference suite * Do README workup and test-case for enum switch/case * Document projections
@saeta I've hit, I think, all the points I intended to. Do you reckon this thing is ready for a merge now? Also curious what you thought of the projection solution? |
@saeta ping! Are there any additional steps to take before getting this initial merge in? |
Hey @eboto I'm sorry for the delay. I think this is in good shape for the initial merge. Thank you very much! |
This is a first attempt at lightweight TS courier binding generation. See the README for what exists and what doesn't.
Been working on this since Monday so I wanted to release some of the code for early review & input.
I've tested these manually against my own
.pdsc
files as well as the reference-suite of.courier
files and it's at the point that all suites compile and visually look good. Next step is to write an npm build that exercises the reference types in runtime. When that satisfies then I'd like to return and clean the code up a bit.Definitely looking for any input on the approach, pitfalls, omitted features, etc. Also I definitely don't feel confident about when
ClassTemplateSpec
s should be used, vs the internalDataSchema
s. I could be doing some boneheaded things here and there so I'd like to understand more about when one is called for vs the other.UPDATE
Just finished cleaning everything up, adding more test cases, etc. This code is ready for a real review and hopefully a merge!