-
Notifications
You must be signed in to change notification settings - Fork 503
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
Better Type Resolution #1673
Comments
Collecting these all in one place is extremely valuable. Question: Is the way TSOA generates/resolves these replicateable by any other libraries in 2024? Essentially, can TSOA make use of a more robust type interpretation tool instead of building it on it's own? Example 1: @Post()
testEndpoint<TMethod extends 'one' | 'two'>(@Path() method: TMethod) {
return method;
}
This is a contrived example, however such usage of generics becomes insanely valuable (required) when safely resolving mapped types directly from action inputs. For example, if Example 2 #1622
|
I think the problem is tsoa tries to generate schemas for all the intermediate types, but obviously a schema cant be made when their generic parameters don't have values, only at the top level where the intermediate type/s are used do the values of the generics come in. I think tsoa should either (although I'm no expert in this): Before that though, I think fixing the linked issue with intersection types should be a lot easier and pertinent Another issue that might be easy is to resolve |
GPT Helped me write this conditional type so I can transform my types without intersections - although it doesnt really solve the issue it works well in some cases. type TransformKeysNoIntersections<T, OmitKeys extends keyof T, OptionalKeys extends keyof T, RequiredKeys extends keyof T> = Omit<{
[P in keyof T]: P extends OptionalKeys
? T[P] | undefined // Mark as optional
: P extends RequiredKeys
? T[P] // Keep as required
: T[P]; // Keep as is
}, OmitKeys>; I actually get the below warning but I can see in swagger that the schema and example are exactly how I specified - with the keys requested made optional, required, or omitted.
There's also this for simpler intersections but both of these utilities suffer from the other issue if theyre used more than a couple levels deep in the typing chain type MergeTypes<T1, T2> = {
[K in keyof T1 | keyof T2]: K extends keyof T2
? T2[K]
: K extends keyof T1
? T1[K]
: never;
}; |
Yes and no. Imo you're correct that rebuilding the Specs from the Typescript AST was viable in a world of simpler types, however, the path forward would definitely be to leverage the TS type checker more. There's some initial work that we never got over the finish line. |
Can you expand on this? Does the 1st party TS ecosystem provide utility today that it did not a few years ago that simplifies this problem? If so, what tools/utilities/programs/APIs are on your mind? Edit: The type checker APIs mentioned here? https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API#type-checker-apis Edit2: Ohhh, the type checker API may actually be it, it seems deceptively straight forward 🤔. Edit3: Found this, but that might not be it: https://github.com/dsherret/ts-morph Edit4: Looks like this lib makes use of the type checker for an implementation example: https://github.com/ts-oas/ts-oas/blob/master/src/lib/SchemaGenerator.ts skimming through it the implementation appears much easier to grok, but that may be up to style difference not implementation differences. |
Is there an intermediary language that can be utilized here to simplify the output needs? Or is that the AST? I've found in other projects where I'm trying to transform one language, data structure, or something else for multiple output use cases, that picking an intermediary language to work with simplifies and decouples the implementation. If anything, it tends to make it easier to reason about. |
@douglasg14b I've looked through some of the Theyre using the same typescript APIs as what you linked and you can see some attempts at updating it - would probably be best to use the typescript APIs directly instead of wrapper libraries, although they could be a good reference.
The FastAPI integration with Pydantic is extremely good and I suggest that I also think it would be better to provide a lot of metadata via decorators rather than jsdoc comments - and also allow choosing a name for the generated schema items e.g. @Model("MyModelName", "Description of MyModel", { example: "of my model" }) The type resolver issues should be a priority though before any of that is considered. |
@vmarchaud If it works as good as it claims in comparison to tsoa - I wish I had known earlier. tsoa caused me so many headaches and wasted time with its type resolution the API looks similar though - it might have been nicer to contribute to tsoa instead. Maybe I will try it and see how it goes. Do you think it would be easy enough to swap out tsoa for typoa? Does it support all the same decorators? EDIT: Looks like it was forked a few years ago - missing a few of the decorators I'm using e.g. |
@WoH considering @vmarchaud comment - it might be good to consider ts-morph |
Feel free to open a PR! |
It might not contain all features that are supported by tsoa (since we wrote it for our usage) but adding middleware shouldn't be that difficult, the codebase is quite small. |
I started using the ts type checker in a personal project and had a look at If I want to understand the Considering the complexity of In saying that @WoH Can you offer any development notes? Root I got the packages subdirs to build - but I don't have any experience working on monorepos like this. Can I install the packages locally and use them in other local projects? Or is any recommendations/notes on debugging/testing? |
I'm not sure where the test fails come from, but you can take a look at the CI, which is the reference point for these, if they wouldn't run there, we'd know. tsoa is 2 packages, the cli, which contains the code -> compiler/type resolver -> metadata -> template & openapi pipeline and the runtime, which contains a few helpers for the code generated via the templates. There should be a vscode test debug config that you can use, we have unit tests Ind integration tests, we will usually always run the cli over a set of fixtures and then perform assertions on them, at least in the code that this would target. The type resolver is the heart of the compiler part. E: Possibly this is what you're also seeing? |
Sorting
I'm submitting a ...
I confirm that I
Behavior
There are multiple issues regarding type resolution (i.e. types to schemas) and use of generics in tsoa.
I suggest other issues be closed and merged into this issue and the type resolution system improved.
The largest issue I have is with resolving intersection types #1067
The second largest issue is with resolution of wrapped types - tsoa seems to want to add them all to my schema but my controllers only return the top level type and I would prefer schemas just be generated for that:
e.g. Gives the error
GenerateMetadataError: No matching model found for referenced type M.
If I explicitly only type the UserReadResponse then tsoa is fine with it - but I would prefer the generics as they're easier to use across multiple controllers
e.g.
Perhaps TSOA should provide a utility type that marks the sub-types to be ignored in schema generation.
Maybe there's another way to declare these types so TSOA could resolve them fine - I would appreciate any hints on that until a better solution can be merged.
Related Issues
Typing to schemas
#1067
#1559
#1327
#1267
#1268
#1547
Generics usage:
#1665
Possibly related:
#705
#1021
I might be willing to help with a PR for this - if @lukeautry or @WoH could let me know where a good place to start would be.
The text was updated successfully, but these errors were encountered: