-
Notifications
You must be signed in to change notification settings - Fork 408
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
Add ts enums #15
Add ts enums #15
Conversation
// or generate literals for the values | ||
|
||
// TODO: what to do in the case where the value is an Object? | ||
// right now we just pring [Object object] as the literal which is bad |
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.
This is the only real concern I have about the code here. I'll call attention to the example of this on the enum test case.
Thanks for the contribution - will take a look this week. |
@@ -0,0 +1,23 @@ | |||
{ |
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.
Don't check this in, I don't use this setup.
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.
This setup doesn't use anything environment-specific. It's generalizable so long as we use mocha, so if someone writes TS in vscode, this run configuration can save them the work of figuring out how to debug tests. I think it adds value, but obviously it's your project so I'll remove it if you still think I should.
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.
I see what you mean. Also I realized that .vscode/settings is already checked in - let's keep this guy here :)
@jcogilvie Again, thanks for the contribution. At a high level, I have a few concerns:
This is useful, but your implementation does not seem to comply with the official spec. See https://github.com/json-schema-org/JSON-Schema-Test-Suite/blob/develop/tests/draft4/ref.json
As commented before, this is a great idea, and should be enabled by default. No need to add the ability to disable export unless you have a compelling use case.
Also a good idea, but see 1.
Another good idea, but the implementation is overly permissive. Again, see the comments. If you want, it could be helpful to split 1+3, 2, and 4 into separate PRs. |
Also please rebase off master and run the linter ( |
How do you feel about marking the generated enum util classes as beta or something, maybe by renaming the setting? I definitely need them as-is for my use case, but I understand that you guys want to discuss them further. I also don't want to spend much longer chasing merges on this PR. It's kind of big. |
Re: $ref implementation, I haven't implemented the full spec for sure, but the spec does call out support for |
Hey @jcogilvie, think you can jump on gitter? https://gitter.im/json-schema-to-typescript/Lobby?utm_source=share-link&utm_medium=link&utm_campaign=share-link |
To sum up yesterday's conversation, I agree that string enums should be represented as string unions. Integer enums should use my new code. If I make that change and kill the util code, will the rest of the PR be accepted as-is? |
…s for int-backed enums and string unions for string-backed
value: string | ||
|
||
constructor(enumValues: string[]) { | ||
let hasValue = !!enumValues[0] |
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.
Is an enum of ['', 'foo']
valid? Should the check be const hasValue = enumValues.length > 0
?
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.
I don't know what what would resolve to, symbolically, when trying to reference the member?
These are only used in the case of integer backed enums, and I can't think of why we would assign ''=0
.
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.
An enum value of 0
is valid, no?
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.
Yeah but I'm not sure a symbolic value of "empty string" is something that we want to produce in an enum declaration. It seems ripe for conflation with null and undefined semantics.
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.
That's fine, but this package should support what TS supports. Ts supports enum a {''}
, so should we.
If you want to avoid empty string enums, I recommend a tslint rule.
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.
We don't generate string identifiers. We generate literal identifiers. So this would be a very special case for a not very often used item, and I'm not sure how we would differentiate it... Our output is:
export enum Bar {
One = 1,
Two = 2,
Three = 3
}
Not
export enum Bar {
"One" = 1,
"Two" = 2,
"Three" = 3
}
Really we need to be worried about what the schema supports--and we support strings or integers as enum member values. If they added ''
as a value in a string enum, it would work fine (as this EnumValue
class is used for int enums only). But as far as our own proprietary extension for the names goes, we can declare whatever requirements we want on those values. An empty string is a special case here (as we don't support any other quoted literal); do you think it's worth the effort?
Although I suppose if you had "''"
(a double-quoted set of single-quotes) as the tsEnumName
in the schema, that might print an empty string as the identifier...
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.
Let's throw an error here, and treat it as tech debt?
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.
Look at the call site for constructing these. This is a zipped array; assuming we pass all other validation for an int enum, what are the possible outcomes here that we need to handle?
I actually think most of this can probably go away... this was used to propagate string values in enum: [...]
up to identifiers for enum declaration, which we no longer do.
var enumValues = zip(rule.tsEnumNames || [],
// If we try to create a literal from an object, bad stuff can happen... so we have to toString it
rule.enum!.map(_ => new TsType.Literal(_).toType(this.settings).toString()))
.map(_ => new TsType.EnumValue(_))
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.
SGTM
I made a last round of comments - it's all minor stuff. The PR looks great @jcogilvie. I look forward to finally getting it merged! In the future, breaking code up into separate PRs by feature could be a good idea :) |
Ha. Yes, this PR grew since I first opened it. My own use case became clearer and I had to add more stuff. In the future I'll probably keep one mainline branch to house all my aggregate changes with individual branches for each. |
@jcogilvie Ping me here when code is ready to go and I'll merge it. |
@bcherny I think we're good to go. |
Looks good - thanks @jcogilvie! |
I added a few things here (with tests):
$ref
, and choose whether to have the referenced types declared with the existingdeclareReferenced
option.tsEnumNames
so that you can specify which integers to use, if you care, like so:This will generate
Additionally any nested enums will be extracted into top-level types.