grantila / typeconv

Convert between JSON Schema, TypeScript, GraphQL, Open API and SureType
MIT License
421 stars 8 forks source link

Typescript type "Date" is misrecognized as user-defined type #17

Open Freedzio opened 2 years ago

Freedzio commented 2 years ago

I have a script running from CLI which transforms typescript definitions to openapi. When having a model like this

export interface MyObject {
  startDate: Date,
  otherProp: string
}

the output is this

{
   "MyObject": {
      "type": "object",
      "properties": {
        "startDate": {
          "$ref": "#/definitions/Date",
          "title": "myObject.startDate"
        },
        "otherProp": {
          "type": "string",
          "title": "myObject.otherProp"
        }
      },
      "required": [
        "startDate",
        "otherProp"
      ],
      "additionalProperties": false,
      "title": "MyObject"
    }
}

The Date type is being interpreted as a user defined type, but it is not. It's a native type

Expected output is

{
   "MyObject": {
      "type": "object",
      "properties": {
        "startDate": {
          "type": "string",
          "format": "date-time",
          "title": "myObject.startDate"
        },
        "otherProp": {
          "type": "string",
          "title": "myObject.otherProp"
        }
      },
      "required": [
        "startDate",
        "otherProp"
      ],
      "additionalProperties": false,
      "title": "MyObject"
    }
}
saayalac commented 2 years ago

Facing same problem

grantila commented 1 year ago

Why do you expect Date in TypeScript to somehow become string in JSON Schema? Surely you need to perform logic on Date to make it a string, such as toString(), toJSON(), toISOString(), toLocaleString() or such. They don't do the same thing, so the date-time JSON Schema format isn't an obvious mapping.

typeconv can't guess how you transform a Date object into a string.

This quite special case with dates, perhaps could benefit from something like special treatment, but I've seen quite a few issues with assumptions of date handling/parsing to/from Date leading to invalid results (e.g. timezone issues).

I would recommend startDate: Date to become startDateUTC: string in your interface. It's clear what it is, and even when it becomes JSON Schema (although you'd lose the format specifier) simply by the name of the property.

Freedzio commented 1 year ago

You seem to be missing my point

typeconv sees Date type as a user defined type and treats it as such. But it is not user defined. One would not expect to set a prop's type Date and see it reference another object in output schema.

My workaround was to define any date containing fields as string, then search for all fields with date in it's name in the output file and change their format to date-time, so it would be displayed as such in swagger ui. In my use case output openapi schema is consumed by java services, hence my need to be it datestring specifically

Although I managed to hack my way around it, it doesn't feel like a proper way to deal with it. Yes, dates are always a pain in the neck, so I'm not surprised that they are problematic in that case aswell. Some flag or something like that would be nice, so the converter would deal with Date type according to user's needs based on that flag

grantila commented 1 year ago

typeconv sees Date type as a user defined type and treats it as such. But it is not user defined. One would not expect to set a prop's type Date and see it reference another object in output schema.

Right, the reason is, it doesn't understand any built-in type. Not Date, not RegExp, not ArrayBuffer, and it doesn't understand how to perfectly 1-to-1 map that to other type systems.

I think it'd make sense to default all of these to any. Maybe with special cases, such as Map<K, V> or Record<K, V> being treated as regular objects for example. Date though, doesn't have one single obvious alternative, like string in your case. Some people would expose it as a number (a unix epoch).

I'm going to give this some thinking, perhaps being able to customize a mapping table yourself (like a .typeconvrc file) would be useful here. Because there's gonna be far more edge cases than Date, once we go down that path.