Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG][typescript-fetch] Additional properties are treated as array #1878

Closed
rzane opened this issue Jan 10, 2019 · 2 comments
Closed

[BUG][typescript-fetch] Additional properties are treated as array #1878

rzane opened this issue Jan 10, 2019 · 2 comments

Comments

@rzane
Copy link

rzane commented Jan 10, 2019

Description
Description

I'm generating a typescript-fetch client using OpenAPI Generator 4.0.0-beta. After running the generator, I notice that the resulting code attempts to coerce a dictionary to an array. According the documentation, a dictionary can be defined by specifying additionalProperties.

openapi-generator version

4.0.0-beta

OpenAPI declaration file content or url
openapi: 3.0.0
info:
  title: MyAPI
  description: MY API
  version: 0.0.0
servers:
  - url: http://localhost:8080/api/
paths:
  /example:
    get:
      operationId: getExample
      responses:
        "200":
          description: "Success"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Example"

components:
  schemas:
    Example:
      type: object
      required:
        - items
      properties:
        items:
          type: object
          additionalProperties:
            type: object
            required:
              - name
            properties:
              name:
                type: string
Command line used for generation
$ node_modules/.bin/openapi-generator generate -i openapi.yaml -o src -g typescript-fetch
Steps to reproduce
$ git clone https://gist.github.com/rzane/99f6106c72bead20faf39c8ad004c4d0 bug-report
$ cd bug-report
$ npm install
$ npm run generate
$ npm run test

You should see the following output:

> tsc -p src --noEmit

src/models/Example.ts:37:9 - error TS2322: Type 'ExampleItems[]' is not assignable to type '{ [key: string]: ExampleItems; }'.
  Index signature is missing in type 'ExampleItems[]'.

37         'items': (json['items'] as Array<any>).map(ExampleItemsFromJSON),
           ~~~~~~~

  src/models/Example.ts:32:5
    32     items: { [key: string]: ExampleItems; };
           ~~~~~
    The expected type comes from property 'items' which is declared here on type 'Example'

src/models/Example.ts:46:19 - error TS2352: Conversion of type '{ [key: string]: ExampleItems; }' to type 'any[]' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
  Type '{ [key: string]: ExampleItems; }' is missing the following properties from type 'any[]': length, pop, push, concat, and 25 more.

46         'items': (value.items as Array<any>).map(ExampleItemsToJSON),
                     ~~~~~~~~~~~~~~~~~~~~~~~~~

The source of the error can be found in src/models/Example.ts, which contains the following:

export function ExampleFromJSON(json: any): Example {
    return {
        'items': (json['items'] as Array<any>).map(ExampleItemsFromJSON),
    };
}

export function ExampleToJSON(value?: Example): any {
    if (value === undefined) {
        return undefined;
    }
    return {
        'items': (value.items as Array<any>).map(ExampleItemsToJSON),
    };
}
Related issues/PRs

I couldn't find one 🤷‍♂️

Suggest a fix

Add a mapValues function to the runtime.ts file:

export function mapValues(data: object, fn: (item: any) => any) {
  return Object.keys(data).reduce(
    (acc, key) => ({ ...acc, [key]: fn(data[key]) }),
    {}
  );
}

Then, in the case of a dictionary, change the above implementation to:

export function ExampleFromJSON(json: any): Example {
  return {
    items: mapValues(json["items"], ExampleItemsFromJSON)
  };
}

export function ExampleToJSON(value?: Example): any {
  if (value === undefined) {
    return undefined;
  }
  return {
    items: mapValues(value.items, ExampleItemsToJSON)
  };
}
@auto-labeler
Copy link

auto-labeler bot commented Jan 10, 2019

👍 Thanks for opening this issue!
🏷 I have applied any labels matching special text in your issue.

The team will review the labels and make any necessary changes.

@ehvattum
Copy link
Contributor

ehvattum commented May 14, 2019

Checking if it is a map is checking the isMapContainer value in the mustache.

I'm currently attempting to implement your suggested fix @rzane

ehvattum added a commit to ehvattum/openapi-generator that referenced this issue May 16, 2019
	Change isContainer -> isListContainer for existing array support.
	Add isMapContainer control flow, adding map support.
	Add utility function to help map openapi map/dictionaries to ts maps.
	Close OpenAPITools#1878
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants