Feature: inline type aliases (@tsoaInline)
See original GitHub issueSorting
-
I’m submitting a …
- bug report
- feature request
- support request
-
I confirm that I
- used the search to make sure that a similar issue hasn’t already been submit
I did, and I found a lot of other similar issues, for example :
Repro project
https://github.com/jeremyVignelles/repro-tsoa/tree/repro/pick-partial-omit
Expected Behavior
Expected swagger.json
{
"components": {
"examples": {},
"headers": {},
"parameters": {},
"requestBodies": {},
"responses": {},
"schemas": {
"User": {
"properties": {
"id": {
"type": "number",
"format": "double"
},
"email": {
"type": "string"
},
"name": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"Happy",
"Sad"
]
},
"phoneNumbers": {
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
"id",
"email",
"name",
"phoneNumbers"
],
"type": "object",
"additionalProperties": false
},
"UserCreationParams": {
"properties": {
"email": {
"type": "string"
},
"name": {
"type": "string"
},
"phoneNumbers": {
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
"email",
"name",
"phoneNumbers"
],
"type": "object"
},
"UserPatchParams": {
"properties": {
"email": {
"type": "string"
},
"name": {
"type": "string"
},
"phoneNumbers": {
"items": {
"type": "string"
},
"type": "array"
},
"status": {
"type": "string",
"enum": [
"Happy",
"Sad"
]
}
},
"type": "object"
}
},
"securitySchemes": {}
},
"info": {
"title": "repro-tsoa",
"version": "1.0.0",
"license": {
"name": "MIT"
},
"contact": {
"name": "John doe",
"email": "example@example.com"
}
},
"openapi": "3.0.0",
"paths": {
"/users/{userId}": {
"get": {
"operationId": "GetUser",
"responses": {
"200": {
"description": "Ok",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
}
}
}
},
"security": [],
"parameters": [
{
"in": "path",
"name": "userId",
"required": true,
"schema": {
"format": "double",
"type": "number"
}
},
{
"in": "query",
"name": "name",
"required": false,
"schema": {
"type": "string"
}
}
]
},
"patch": {
"operationId": "PatchUser",
"responses": {
"204": {
"description": "No content"
}
},
"security": [],
"parameters": [
{
"in": "path",
"name": "userId",
"required": true,
"schema": {
"format": "double",
"type": "number"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UserPatchParams"
}
}
}
}
}
},
"/users": {
"post": {
"operationId": "CreateUser",
"responses": {
"201": {
"description": "Created"
}
},
"security": [],
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UserCreationParams"
}
}
}
}
}
}
},
"servers": [
{
"url": "/"
}
]
}
/**
* @tsoaInline
*/
export type UserCreationParams = Pick<User, "email" | "name" | "phoneNumbers">;
/**
* @tsoaInline
*/
export type UserPatchParams = Partial<Omit<User, "id">>
Current Behavior
Generated swagger.json
{
"components": {
"examples": {},
"headers": {},
"parameters": {},
"requestBodies": {},
"responses": {},
"schemas": {
"User": {
"properties": {
"id": {
"type": "number",
"format": "double"
},
"email": {
"type": "string"
},
"name": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"Happy",
"Sad"
]
},
"phoneNumbers": {
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
"id",
"email",
"name",
"phoneNumbers"
],
"type": "object",
"additionalProperties": false
},
"Pick_User.email-or-name-or-phoneNumbers_": {
"properties": {
"email": {
"type": "string"
},
"name": {
"type": "string"
},
"phoneNumbers": {
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
"email",
"name",
"phoneNumbers"
],
"type": "object",
"description": "From T, pick a set of properties whose keys are in the union K"
},
"UserCreationParams": {
"$ref": "#/components/schemas/Pick_User.email-or-name-or-phoneNumbers_"
},
"Partial_Omit_User.id__": {
"properties": {
"email": {
"type": "string"
},
"name": {
"type": "string"
},
"phoneNumbers": {
"items": {
"type": "string"
},
"type": "array"
},
"status": {
"type": "string",
"enum": [
"Happy",
"Sad"
]
}
},
"type": "object",
"description": "Make all properties in T optional"
},
"UserPatchParams": {
"$ref": "#/components/schemas/Partial_Omit_User.id__"
}
},
"securitySchemes": {}
},
"info": {
"title": "repro-tsoa",
"version": "1.0.0",
"license": {
"name": "MIT"
},
"contact": {
"name": "John doe",
"email": "example@example.com"
}
},
"openapi": "3.0.0",
"paths": {
"/users/{userId}": {
"get": {
"operationId": "GetUser",
"responses": {
"200": {
"description": "Ok",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
}
}
}
},
"security": [],
"parameters": [
{
"in": "path",
"name": "userId",
"required": true,
"schema": {
"format": "double",
"type": "number"
}
},
{
"in": "query",
"name": "name",
"required": false,
"schema": {
"type": "string"
}
}
]
},
"patch": {
"operationId": "PatchUser",
"responses": {
"204": {
"description": "No content"
}
},
"security": [],
"parameters": [
{
"in": "path",
"name": "userId",
"required": true,
"schema": {
"format": "double",
"type": "number"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UserPatchParams"
}
}
}
}
}
},
"/users": {
"post": {
"operationId": "CreateUser",
"responses": {
"201": {
"description": "Created"
}
},
"security": [],
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UserCreationParams"
}
}
}
}
}
}
},
"servers": [
{
"url": "/"
}
]
}
Note that the type alias are generated as
"UserCreationParams": {
"$ref": "#/components/schemas/Pick_User.email-or-name-or-phoneNumbers_"
},
which could be simplified as client code generators (like NSwag) are unable to handle this properly.
Possible Solution
As mentionned above, there could be a JSDoc annotation that would allow to inline the type alias to flatten its type aliases indirections.
Steps to Reproduce
- clone https://github.com/jeremyVignelles/repro-tsoa/tree/repro/pick-partial-omit
- yarn build
- See build/swagger.json
Context (Environment)
Version of the library: 3.5.2 Version of NodeJS: 14
- Confirm you were using yarn not npm: [X]
Detailed Description
The jsdoc annotation can be placed on a type
declaration, like so:
export interface User {
id: number;
email: string;
name: string;
status?: "Happy" | "Sad";
phoneNumbers: string[];
}
/**
* A post request should not contain an id.
* @tsoaInline
*/
export type UserCreationParams = Pick<User, "email" | "name" | "phoneNumbers">;
If both types are used, the above code would generate the same thing as if they were in fact two separate interfaces, that is, the same as :
export interface User {
id: number;
email: string;
name: string;
status?: "Happy" | "Sad";
phoneNumbers: string[];
}
/**
* A post request should not contain an id.
*/
export interface UserCreationParams {
email: string;
name: string;
phoneNumbers: string[];
}
Breaking change?
No, the new syntax would be opt-in
Issue Analytics
- State:
- Created 3 years ago
- Reactions:11
- Comments:5 (2 by maintainers)
Top Results From Across the Web
How To Use Type Aliases in TypeScript - DigitalOcean
In this tutorial, you will refactor code that uses string literals to include aliases. You will be able to use and understand TypeScript...
Read more >Feature request - inline type aliases : r/typescript - Reddit
Is there a problem with the function not returning the alias, only returning the inferred object? You are still getting all the type...
Read more >Kotlin: Type Aliases and Inline Classes | by Forketyfork - Medium
The Kotlin programming language has two distinct features that may be used for similar purposes. Those are inline classes and type aliases.
Read more >Type Aliases vs Inline Classes - GeeksforGeeks
Inline classes add the features of TypeAliases with value range of primitive data types. In some situations it is needed to create a...
Read more >Kotlin: Type aliases and inline classes | by Filipe Batista
Kotlin is a modern programming language and so today we are going to see two cool features: type aliases and inline classes.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
There is a workaround for this, although not pretty. You first need to make sure that you only use interfaces on your API, so replace
by
Then, you need to flatten the base type on the right, for which you can use a helper type like this:
Now
UserCreationParams
gets generated the way you would expect.+1 to flatten unneeded utility types or at least add a naming option