Tsoa: undefined is not supported in model properties

Created on 19 Jan 2021  Â·  5Comments  Â·  Source: lukeautry/tsoa

Sorting

  • I'm submitting a ...

    • [ ] bug report
    • [x] feature request
    • [ ] support request
  • I confirm that I

    • [x] used the search to make sure that a similar issue hasn't already been submit

Expected Behavior

I would like to use models that can have the undefined type:

import {Controller, Get, Route} from 'tsoa';

interface User {
  name: string | undefined;
}

@Route('user')
export class UserController extends Controller {
  @Get()
  public async getUser(): Promise<User> {
    return {name: undefined};
  }
}

Current Behavior

I get an error when trying to generate the spec:

yarn tsoa spec
yarn run v1.22.4
$ /Users/cedric/dev/kraaft-firebase/app-engine/node_modules/.bin/tsoa spec
There was a problem resolving type of 'User'.
Generate swagger error.
 Error: Unknown type: UndefinedKeyword
At: src/api/userController.ts:10:10.
This was caused by 'string | undefined'
    at new GenerateMetadataError (/Users/cedric/dev/kraaft-firebase/app-engine/node_modules/tsoa/node_modules/@tsoa/cli/dist/metadataGeneration/exceptions.js:22:28)
    at TypeResolver.resolve (/Users/cedric/dev/kraaft-firebase/app-engine/node_modules/tsoa/node_modules/@tsoa/cli/dist/metadataGeneration/typeResolver.js:308:19)
    at /Users/cedric/dev/kraaft-firebase/app-engine/node_modules/tsoa/node_modules/@tsoa/cli/dist/metadataGeneration/typeResolver.js:113:95
    at Array.map (<anonymous>)
    at TypeResolver.resolve (/Users/cedric/dev/kraaft-firebase/app-engine/node_modules/tsoa/node_modules/@tsoa/cli/dist/metadataGeneration/typeResolver.js:112:45)
    at TypeResolver.propertyFromSignature (/Users/cedric/dev/kraaft-firebase/app-engine/node_modules/tsoa/node_modules/@tsoa/cli/dist/metadataGeneration/typeResolver.js:761:143)
    at /Users/cedric/dev/kraaft-firebase/app-engine/node_modules/tsoa/node_modules/@tsoa/cli/dist/metadataGeneration/typeResolver.js:727:161
    at Array.map (<anonymous>)
    at TypeResolver.getModelProperties (/Users/cedric/dev/kraaft-firebase/app-engine/node_modules/tsoa/node_modules/@tsoa/cli/dist/metadataGeneration/typeResolver.js:727:124)
    at TypeResolver.getModelReference (/Users/cedric/dev/kraaft-firebase/app-engine/node_modules/tsoa/node_modules/@tsoa/cli/dist/metadataGeneration/typeResolver.js:552:31)

Possible Solution

The attribute could be treated as if it was optional.

Steps to Reproduce

  1. create a controller like the one above
  2. generate the spec: yarn tsoa spec

Context (Environment)

Version of the library: 3.4.0
Version of NodeJS: v10.21.0

  • Confirm you were using yarn not npm: [x]

Detailed Description

Breaking change?

No

Stale

Most helpful comment

OpenAPI 2/3 does not support an undefined type, only optional properties. We still want to distinguish between null and undefined, so modeling this in TS using

interface User {
  name?: string;
}

is the best way to represent this currently.
The proper way to solve this would be to add a Tsoa.UndefinedType, which marks the property as optional if it is a property type and handles the case where it is not, for example a route handler: public getStuff(): undefined.

All 5 comments

Same problem here ✋

Version of the library: 3.4.0
Version of NodeJS: v15.5.0

Checking TypeResolver.resolve method, there isn't a validation for ts.SyntaxKind.UndefinedKeyword so this throws the exception on line 288. I made a quick experiment adding a simple || in ts.SyntaxKind.NullKeyword case:

if (this.typeNode.kind === ts.SyntaxKind.NullKeyword 
    || this.typeNode.kind === ts.SyntaxKind.UndefinedKeyword) {

    var enumType = {
        dataType: 'enum',
        enums: [null],
    };

   return enumType;
 }

With this change ts.SyntaxKind.UndefinedKeyword is treated as null type and the error won't happen. However, this doesn't treat the field as optional and i don't think the solution would be as simple as that 😅. I hope this info can be helpful

OpenAPI 2/3 does not support an undefined type, only optional properties. We still want to distinguish between null and undefined, so modeling this in TS using

interface User {
  name?: string;
}

is the best way to represent this currently.
The proper way to solve this would be to add a Tsoa.UndefinedType, which marks the property as optional if it is a property type and handles the case where it is not, for example a route handler: public getStuff(): undefined.

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days

@WoH would you be able to elaborate on what you mentioned?

The proper way to solve this would be to add a Tsoa.UndefinedType

Is this something we can do in our code, or is this a suggested change to TSOA that one could raise as a PR?

I'd really love undefined to be treated as an optional property: the convention in our codebase is to avoid ? to prevent refactoring errors where a new (optional) property is added to a type, but the developer forgets to set it in all places. By using | undefined the developer is forced to think about whether the property needs setting to undefined or some other value.

Is this something we can do in our code, or is this a suggested change to TSOA that one could raise as a PR?

The latter

Was this page helpful?
0 / 5 - 0 ratings