-
Notifications
You must be signed in to change notification settings - Fork 504
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
Correctly generate types for Record<string, T> #1456
Conversation
When encountering a Record whose key is string, tsoa would previously generate a blank object. This change allows the type resolver to recognize the record and generate its value type properly. Intended to fix lukeautry#1407
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.
Hello there ryanisaacg 👋
Thank you and congrats 🎉 for opening your first PR on this project.✨
We will review the following PR soon! 👀
Best way to show this is to add a property to the Test Model here: And do assertions for the type here: and here: |
@@ -420,6 +420,20 @@ export class TypeResolver { | |||
return stringMetaType; | |||
} | |||
|
|||
if (typeReference.typeName.text === 'Record' && typeReference.typeArguments?.length === 2) { | |||
const indexType = new TypeResolver(typeReference.typeArguments[0], this.current, this.parentNode, this.context).resolve(); | |||
if (indexType.dataType === 'string') { |
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.
Why only for string? We should be able to handle numbers, boolean, string enums, number enums etc.?
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 number callout! I've added support here for numbers and test cases to verify
- number enums and string enums are handled separately (I'm not sure where, but as you can see from the test suite they are handled correctly). They actually produce fairly different OpenAPI results, because of the way swagger handles dictionaries
boolean
is not a validRecord
key type; the type forRecord
's key isstring | number | symbol
.symbol
isn't supported by tsoa it seems (which makes sense, because it doesn't belong in a public-facing API)
if (typeReference.typeName.text === 'Record' && typeReference.typeArguments?.length === 2) { | ||
const indexType = new TypeResolver(typeReference.typeArguments[0], this.current, this.parentNode, this.context).resolve(); | ||
if (indexType.dataType === 'string') { | ||
const valueType = new TypeResolver(typeReference.typeArguments[1], this.current, this.parentNode, this.context).resolve(); |
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.
In case we are passing from parent (GenericModel has items: Record<string, T>) can you handle these without amending the context? (IIRC that should be created on processing the GenericModel<T>
, but it would also be a good test probably.
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.
How would I go about doing that? Should I be creating a new temporary context?
I'm not familiar with the codebase so I'm not sure what the context is here, or what purpose it serves, so I just followed the structure of other cases in this method.
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 should be handled for you at this point already.
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.
Sorry, I'm not sure what you mean.
- Rename the existing 'record' test into 'stringUnionRecord' to distinguish it from the new test cases - Add a 'numberUnionRecord' test case, which tests the same path as 'stringUnionRecord' - Add two new cases, 'stringRecord' and 'numberRecord', which test Record<string, T> and Record<number, T>
Thanks for the pointers! I've now added tests to cover my changes. |
When encountering a Record whose key is string, tsoa would previously generate a blank object. This change allows the type resolver to recognize the record and generate its value type properly.
I would love guidance on where to add some tests for this PR! The test suite is a little opaque to me.
All Submissions:
Closing issues
Closes #1407
If this is a new feature submission:
Potential Problems With The Approach
Test plan