Skip to content
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

Helper to construct TypeSpec unions out of existing models #1811

Closed
tjprescott opened this issue Apr 10, 2023 · 5 comments
Closed

Helper to construct TypeSpec unions out of existing models #1811

tjprescott opened this issue Apr 10, 2023 · 5 comments
Assignees
Labels
design:needed A design request has been raised that needs a proposal
Milestone

Comments

@tjprescott
Copy link
Member

Background
PR #1770 required logic that would essentially take the response types of multiple operations with shared routes and emit them as "oneOf" properties in OpenAPI3. That should have been an easy task, especially since the OpenAPI3 emitter already had logic to get the appropriate OpenAPI3 schema for existing TypeSpec types, including Union.

However, this proved infuriatingly difficult because there was no way to simply take two models and say "Please give me a TypeSpec Union of these" that I could pass to that existing logic. If you can't work with the TypeSpec types as output by the compiler, you are screwed and have to invent a bunch of intermediate models to facilitate this. It ended up being way more work than it seems like it should have.

Request
It would be nice to have some kind of helper method that takes an arbitrary number of TypeSpec types and returns a TypeSpec.Union of them, but without all the type graph links that make trying to construct one of these programmatically pretty much impossible (nodes, parents, etc.).

Perhaps there could be a way to generalize this, but essentially constructing TypeSpec types seems to only be possible via the compiler, and it would be useful to be able to create them programmatically as well.

@bterlson
Copy link
Member

A library to aid in constructing ephemeral types for emitters would definitely be nice. That said, you can fairly easily do the same code the checker does for creating a union, since createType is exported, I think?

@tjprescott
Copy link
Member Author

It doesn't look like createType<T> is exported. https://github.com/microsoft/typespec/blob/main/packages/compiler/core/checker.ts#L3630

@bterlson
Copy link
Member

It is, on the checker instance:

@tjprescott
Copy link
Member Author

@bterlson I tried this and it didn't work for the reasons that it seems to need a bunch of underlying TypeSpec nodes and so forth:

      // statusCodeResponses contains the different responses that need to be combined into a union
      const variants: UnionVariant[] = [];
      const union = program.checker.createType({
        kind: "Union",
        node: undefined,
        decorators: [],
        variants,
        get options() {
          return Array.from(this.variants.values()).map((v) => v.type);
        },
        expression: false,
      });
      for (const response of statusCodeResponses) {
        const variant = program.checker.createType({
          kind: "UnionVariant",
          type: response.type,
          name: Symbol("name"),
          decorators: [],
          node: undefined,
          union: union,
        });
        variants.push(variant as UnionVariant);

I get an error on the last line: The types of 'union.node' are incompatible between these types. Type 'undefined' is not comparable to type 'UnionStatementNode | UnionExpressionNode'.

@tjprescott tjprescott removed their assignment Apr 19, 2023
@markcowl markcowl added the design:needed A design request has been raised that needs a proposal label Apr 24, 2023
@markcowl markcowl added this to the [2023] June milestone Apr 24, 2023
@markcowl markcowl modified the milestones: [2023] June, Backlog Jun 1, 2023
@timotheeguerin
Copy link
Member

this is covered by the typekits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
design:needed A design request has been raised that needs a proposal
Projects
None yet
Development

No branches or pull requests

4 participants