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

Support generics #1082

Open
lfportal opened this issue Oct 22, 2020 · 3 comments
Open

Support generics #1082

lfportal opened this issue Oct 22, 2020 · 3 comments
Labels
enhancement New feature or request

Comments

@lfportal
Copy link
Contributor

I also noticed the following which capability matrix:
union type -> ✅
inheritance type -> ✅
recursive -> 🔴
generics -> 🔴

Would love to hear any thoughts you have on implementing these.

Originally posted by @mahirk in #1034 (comment)

@lfportal
Copy link
Contributor Author

interface Generic<T> {
  genericProp: T;
}

type A = Generic<String>

Off the top of my head:

  1. Parse type parameters (T)
  2. Parse the generic interface, passing in the resolved type parameters

Questions that need answering:

  • Do we store the resulting type in the typeTable?
    • I'm thinking we don't, and treat it as if it were defined inline (i.e. type A = { genericProp: String; }) to keep it simple
    • If we do, the need some way to name the type. GenericString, GenericInt? But this could lead to type name clashes

Thoughts @mahirk?

#1034 (comment)

Just to confirm we will store Generic in the typeTable regardless of we storing the resulting types, right?

inline type works great when the Generic object is small, but when its big and frequently referenced, the cost of expanding it every where goes up very quickly. The name clashes should not be a problem if we just use the full name Generic<String>. Maybe we can have a threshold on when we should put it into typeTable?

#1034 (comment) @Noeyfan

The type table is used to generate the components section of OpenAPI documents. We would require some strategy to convert Generic<String> into something OpenAPI friendly. Whatever that becomes will be subject to name clashing with user defined types (this will be true for typescript's utility types too). I think we should aim to avoid any implicit naming, and stick with a clear and predictable syntax. Currently the type table only stores types declared using type aliases and interfaces. I don't see any need to complicate this:

body: {
  a: Generic<String>; // inline type, rendered as an inline schema in OpenAPI
  b: MyType; // reference type, rendered as a $ref schema in OpenAPI
}

type MyType = Generic<String> // stored in type table

#1034 (comment)

@lfportal lfportal added the enhancement New feature or request label Oct 22, 2020
@ccakes
Copy link

ccakes commented Nov 6, 2020

+1 for this, an example use case I have would be something like this:

import { api, endpoint, request, response, body } from "@airtasker/spot";

@api({
  name: "My API"
})
class Api {}

@endpoint({
  method: "POST",
  path: "/users"
})
class CreateUser {
  @request
  request(@body body: CreateUserRequest) {}

  @response({ status: 201 })
  response(@body body: StandardResponse<CreateUserResponse>) {}
}

/**
 * A wrapper for all response types
 */
interface StandardResponse<T = undefined> {
  traceId: string;
  message: string;
  data: T
}

interface CreateUserRequest {
  firstName: string;
  lastName: string;
}

interface CreateUserResponse {
  firstName: string;
  lastName: string;
  role: string;
}

@benjaminlgt
Copy link

Hi @lfportal, might there still be interest in this issue, I have something WIP that works for my use case.
Might I also ask if you have CLA requirements for code contributions. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants