Tsoa: Unknown type: TypeLiteral when using a dictionary on a model object

Created on 1 Feb 2017  路  15Comments  路  Source: lukeautry/tsoa

Hi,

When I try and generate the model I get this error:

  Unknown type: TypeLiteral

I thought I knew what was causing this, but its clear now that I don't. Its from one of my models, but that's about it.

Any suggestions?

bug enhancement help wanted

All 15 comments

I guess this is a common issue for anonymous types. Either a type name needs to be generated, or more meaningful error reported. @lukeautry what's your position on this? I was looking into this for hashmaps support (field: {[key:string]: xxxxx};) - may as well fix this if you'll approve type generation

I think we should be able to process anonymous types, but I don't think we should generate interfaces for them or anything. I think we should simply have inline descriptions in the swagger spec with the properties contained in that anonymous type.

Any update on that?

+1 This would definitely be a great improvement : Being forced to define distinct classes for properties that will never exist by themselves is painful and add unnecessary complexity to the documentation.

@ThorstenBux / @fhewitt / @donahchoo / @manast-apsis if tsoa were to generate the swagger model "on-the-fly" it doesn't have a name for the model. And that's the problem, swagger requires a name for the "$ref" (see here). So my question for you is, how would you like it create that name?

An example @manast-apsis provided looks like this:

class myClass {
    nodes: {
        [nodeName: string]: Node;
    };
}

I imagine that we could create something like RecordOfNodeNameToNodeValue since that would be RecordOf{indexName}To{valueType}Value. But even then, I'm wondering if we would get collisions. For instance:

export interface ModelToUser {
    toys: {
        [key: string]: any
    },
    chores {
        [key: string]: any
    }
}

That would produce to $refs with the same name RecordOfKeyToAnyValue.

I'm just raising some scenarios. Also I'd love your input to know what you'd like the auto-generated name to look like. I'll add the [Help Wanted] PR to this so new contributors can give it a shot.


P.S. it's been mentioned before, but the workaround is to make explicit interfaces (even if that is unpalatable for some). So in the case of the MyClass.nodes issue I presented above, the current solution would be

interface INodeDictionary {
    [nodeName: string]: Node;
}
class myClass {
    nodes: INodeDictionary;
}

This is super helpful for us. Would it be possible to get a release soon with all the recent improvements? Thanks

@javichi I just pushed version 2.5.0 that allows nested anonymous types. Please let us know if it works for you so we can consider closing this isue. Btw, I don't think it allows it at the first level because we need to be able to create a $ref name in swagger. So don't expect something like this to work:

    @Post()
    public async Create(@Body() user: IUserAbstraction): Promise<{foo: string}> {
        // ...
    }

However, I believe that PR #415 allows you to do this:

    export interface IHaveAnAnonymousChild {
      foo: string,
      nestedAnonymous: {
        bar: string
      }
    }

    @Post()
    public async Create(@Body() user: IUserAbstraction): Promise<IHaveAnAnonymousChild> {
        // ...
    }

@ThorstenBux / @fhewitt / @donahchoo / @manast-apsis now that this feature was released in v2.5.0 if you could test and let us know what you think, that would really help us! :) See above for potential limitations.

@dgreene1 You should try (inlining inside the Promise) :wink:

Trying 2.5.0. I still can't get dictionaries of model objects to work properly. For example the following model:

export interface AccountUser {
  _id: string;
  email: string;
  role: AccountUserRole;
  status: AccountUserStatus;
  actions: AccountUserAction[];
}

export interface AccountEntity {
  _id: string;
  type: string;
  name: string;
  address: string;
  lat?: number;
  long?: number;
  users: {
    [k: string]: AccountUser;
  };
}

is generating the following swagger model with tsoa v2.5.0:

{
  "_id": "string",
  "type": "string",
  "name": "string",
  "address": "string",
  "lat": 0,
  "long": 0,
  "users": {}
}

I noticed a difference though, before 2.5.0 it was including an additionalProp1 key inside the model that has now disappeared in 2.5.0

{
  "_id": "string",
  "type": "string",
  "name": "string",
  "address": "string",
  "lat": 0,
  "long": 0,
  "users": {
    "additionalProp1": {}
  }
}

@javichi I鈥檝e reopened #374 for you which is more closely related to your specific use case.

As for the additionalProp1, it seems to me that it never should have been there, right? Like it鈥檚 good that it鈥檚 gone now, correct?

Yes, I think https://github.com/lukeautry/tsoa/issues/374 covers the issue i explained better.

Hey
I'm using 2.5.9 and still seeing

additionalProp1 at the end of every post request on swagger
Any idea why?

@oreporan no one has reported that bug yet. So can you please create a github issue and be careful to fill out all of the information so we can reproduce it?

Please include all of your typescript interfaces and your route controllers.

you can set it in tsoa.config, inside the swagger block:

  "noImplicitAdditionalProperties": "silently-remove-extras"

Hope it helps

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rdhelms picture rdhelms  路  4Comments

rustam-crunch picture rustam-crunch  路  5Comments

jfrconley picture jfrconley  路  3Comments

amcdnl picture amcdnl  路  6Comments

sundowndev picture sundowndev  路  4Comments