Skip to content

Property without type should be declared as unknown #1039

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

Closed
1 task done
ggrossetie opened this issue Feb 27, 2023 · 9 comments · Fixed by #1049
Closed
1 task done

Property without type should be declared as unknown #1039

ggrossetie opened this issue Feb 27, 2023 · 9 comments · Fixed by #1049

Comments

@ggrossetie
Copy link

Description

Name Version
openapi-typescript 6.1.1
Node.js 18.12.2
OS + version Ubuntu 22.04.2

Reproduction

  1. Create a file named api.json with the following content:

api.json

{
  "openapi": "3.0.0",
  "components": {
    "schemas": {
      "User": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "Info": {
            "nullable": false
          }
        }
      }
    }
  }
}
  1. Run openapi-typescript:
$ npx openapi-typescript api.json --output type.ts
✨ openapi-typescript 6.1.1
🚀 api.json → file:///path/to/type.ts [12ms]
  1. You should get the following result:

type.ts

/**
 * This file was auto-generated by openapi-typescript.
 * Do not make direct changes to the file.
 */


export type paths = Record<string, never>;

export type webhooks = Record<string, never>;

export interface components {
  schemas: {
    User: {
      Info?: Record<string, never>;
    };
  };
  responses: never;
  parameters: never;
  requestBodies: never;
  headers: never;
  pathItems: never;
}

export type external = Record<string, never>;

export type operations = Record<string, never>;

As you can see, schemas.User.Info is defined as Record<string, never> which is incorrect because Info might contain a string, number or boolean and not necessarily an object.

Expected result

export interface components {
  schemas: {
    User: {
      Info?: unknown;
    };
  };
  responses: never;
  parameters: never;
  requestBodies: never;
  headers: never;
  pathItems: never;
}

Checklist

@ggrossetie
Copy link
Author

It might be the same as #1031 and might be resolved by #1032

@duncanbeevers could you please confirm (or not) that this is the same issue?

@duncanbeevers
Copy link
Contributor

duncanbeevers commented Mar 1, 2023

Yes, I can confirm that #1032 would resolve this issue.

image

The type of Info is still a Record, which is a little odd; as you pointed-out @ggrossetie, Info could be a string, a boolean, a number, etc…

I think your proposal that Info should be typed as unknown is correct.

@ggrossetie
Copy link
Author

Thanks!
I will keep this issue open since it goes a bit further and suggest to use unknown instead of Record<string, unknown> when the type is unknown.

@drwpow
Copy link
Contributor

drwpow commented Apr 5, 2023

I believe this is taken care of by the --empty-objects-unknown flag introduced in #1032. I’m still somewhat against loosening up the output types to unknown or even Record<string, unknown> as default behavior (explanation).

I also don’t want to debate this topic too much more, because I think no matter how you answer the question “what types should be generated when my schema doesn’t specify a type” isn’t a very productive conversation. No matter what the decision is, the fact is that your schema is lacking critical information needed to type it safely. And I’d rather err on the side of generating types to encourage you to fix it at the schema level, not the typegen level.

@duncanbeevers
Copy link
Contributor

And I’d rather err on the side of generating types to encourage you to fix it at the schema level, not the typegen level.

I agree with this stance. Strict-by-default guides API designers towards better schemas.

Importantly though, this tool is used to generate types for APIs outside of one's own control, so having controls for loosening the generated types is key.

@mitchell-merry
Copy link
Contributor

mitchell-merry commented Apr 5, 2023

Importantly though, this tool is used to generate types for APIs outside of one's own control, so having controls for loosening the generated types is key.

Exactly.

Besides, I don't see why a discussion is necessary, since the spec is well-defined for these cases as I've demonstrated. Specs of this form - without type specified - are perfectly legal according to the spec, but you're choosing here to not support them correctly. Why? What if we genuinely want to accept an unknown type? (that is, any value? number, string, boolean, array, object, whatever)

Realistically, if this doesn't make it into project, I'm just going to have to complicate generation on my side as I'll need to use the Node API and specify a custom transform, and then implement this logic myself.

@drwpow
Copy link
Contributor

drwpow commented Apr 5, 2023

@mitchell-merry Sorry—just for clarification, is the --empty-objects-unknown flag not generating what you’d like? It would be helpful for me to clearly see the differences between a) the default generation, b) --empty-objects-unknown, and c) what your proposal is. Just so we’re all on the same page.

@drwpow
Copy link
Contributor

drwpow commented Apr 5, 2023

Oh, sorry—I understand now. Yes that doesn’t conflict and this should be fixed (rubber ducking works!). I’ll re-open your PR.

@ggrossetie
Copy link
Author

It would be helpful for me to clearly see the differences between a) the default generation, b) --empty-objects-unknown, and c) what your proposal is. Just so we’re all on the same page.

Sure, I will do that tomorrow but I believe it's:

a)

Record<string, never>

b)

Record<string, unknown>

c)

unknown

(as mentioned by @duncanbeevers in #1039 (comment))
But I will confirm tomorrow using the latest release.

Oh, sorry—I understand now. Yes that doesn’t conflict and this should be fixed (rubber ducking works!). I’ll re-open your PR.

No worries 😉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants