tsoa: Union with null is not supported

TSOA fails on generating routes when interface includes ‘null’ type.

  • 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

Expected Behavior

Generate propper swagger for empty-valued patams

Current Behavior

Error is presented:

Generate routes error.
 Error: Unknown type: NullKeyword
    at new GenerateMetadataError (/Users/atom/Projekty/atom/107/dcs-api/node_modules/tsoa/dist/metadataGeneration/exceptions.js:20:28)
    at TypeResolver.resolve (/Users/atom/Projekty/atom/107/dcs-api/node_modules/tsoa/dist/metadataGeneration/typeResolver.js:153:19)
    at /Users/atom/Projekty/atom/107/dcs-api/node_modules/tsoa/dist/metadataGeneration/typeResolver.js:567:152
    at Array.map (<anonymous>)
    at TypeResolver.getModelProperties (/Users/atom/Projekty/atom/107/dcs-api/node_modules/tsoa/dist/metadataGeneration/typeResolver.js:555:18)
    at TypeResolver.getReferenceType (/Users/atom/Projekty/atom/107/dcs-api/node_modules/tsoa/dist/metadataGeneration/typeResolver.js:352:35)
    at TypeResolver.resolve (/Users/atom/Projekty/atom/107/dcs-api/node_modules/tsoa/dist/metadataGeneration/typeResolver.js:202:30)
    at /Users/atom/Projekty/atom/107/dcs-api/node_modules/tsoa/dist/metadataGeneration/typeResolver.js:567:152
    at Array.map (<anonymous>)
    at TypeResolver.getModelProperties (/Users/atom/Projekty/atom/107/dcs-api/node_modules/tsoa/dist/metadataGeneration/typeResolver.js:555:18)

Steps to Reproduce

  1. Create interface in eg:
interface IServerSessionDetails {
   id: number,
   name: string,
   emptyVal: string | null
}

2.run routes generation

Context (Environment)

Version of the library: 2.5.2 Version of NodeJS: 8.15 & 10.15

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

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 5
  • Comments: 29 (9 by maintainers)

Most upvoted comments

@dgreene1

Sorry for not checking this for such a long time.

I’m not using the ? operator because I want my response to be strict and full even if value is null.

So, lets say we have interface:

interface IServerSessionDetails {
   id: number,
   name: string,
   emptyVal: string | null
}

According to this description, this will result in REST response of format:

{
 id: 1
 name: "NameValue"
 emptyVal: null 
}

While

interface IServerSessionDetails {
   id: number,
   name: string,
   emptyVal?: string 
}

Will result in:

{
 id: 1
 name: "NameValue"
}

So, those responses will not be the same. At least this is how I and most of the devs I know will react to that kind of typing. ? indicates the property is optional and might be not present in the serialized response. This means the de-serializer has to be prepared that $.emptyVall might be undefined and not exists. null|string ensures that prop is in the response, and the de-serializer does not have to check for the existence of prop, just for its nullability or not.

This is how it works for example with https://github.com/typestack/class-transformer.

Property marked as ? can be undefined, thus will not exist in serialized object Propertyt typed as |null will be serialized as =null.

There’s just a difference between null, which is some kind of information, and no information.

Bumping this thread now that the “null” type has been added to OpenAPI.

An example model of:

SomeModel {
    nullableField: string | null;
}

Should generate a spec of:

{
"type": "object"
"properties": {
    "nullableField": {
        "type": ["string", "null"]
    }
}

When working with relational db i don’t think last_name?: string is more common

I’d encourage you and anyone reading this keep your tsoa types separate from your database types. It’s incredibly valuable for software to use abstractions. This allows your database to change and evolve while keeping your contract the same for consumers.

I realize that I’ve just given unsolicited architectural advice, so please forgive me.

But it’s still unclear to me how we can support string | null when Swagger/OpenAPI doesn’t support it.

I think at best we can log a warning to console that says, “please use string | undefined instead.” Because that’s the only “nullable” concept that Swagger/OpenAPI supports. And it’s part of our design goals to only validate types that can be communicated with OpenAPI. When/if OpenAPI supports string | null I will be the first to push for support with tsoa.