Open lfportal opened 3 years ago
interface Generic<T> { genericProp: T; } type A = Generic<String>
Off the top of my head:
- Parse type parameters (
T
)- 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 clashesThoughts @mahirk?
https://github.com/airtasker/spot/issues/1034#issuecomment-704566174
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?
https://github.com/airtasker/spot/issues/1034#issuecomment-713305288 @Noeyfan
The type table is used to generate the
components
section of OpenAPI documents. We would require some strategy to convertGeneric<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 usingtype
aliases andinterfaces
. 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
https://github.com/airtasker/spot/issues/1034#issuecomment-714377270
+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;
}
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!
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 https://github.com/airtasker/spot/issues/1034#issuecomment-699204533