RicoSuter / NSwag

The Swagger/OpenAPI toolchain for .NET, ASP.NET Core and TypeScript.
http://NSwag.org
MIT License
6.79k stars 1.29k forks source link

Typescript - can't compile in strict mode - null args for array.push problem #3811

Open MirKml opened 2 years ago

MirKml commented 2 years ago

With NSwag toolchain v13.15.5.0 (NJsonSchema v10.6.6.0 (Newtonsoft.Json v11.0.0.0)) (http://NSwag.org) OpenAPI spec with models and arrays is converted to Typescript. It can't be compiled with strict settings. It produces errors

src/ApiClient.ts(297,39): error TS2345: Argument of type 'VehicleInfo | null' is not assignable to parameter of type 'VehicleInfo'.
  Type 'null' is not assignable to type 'VehicleInfo'.

This is the problematic code - in VehiclesInfoResponse.init method

image

It works when Typescript compiler option strictNullChecks is set to false.

OpenAPI yaml

openapi: 3.0.0
servers:
  - description: current API version base path
    url: /v6
info:
  version: "6.9.0"
  title: test
  contact:
    email: info@info.com
  license:
    name: Apache 2.0
    url: "http://www.apache.org/licenses/LICENSE-2.0.html"

paths:
  /getVehiclesInfo:
    get:
      summary: Returns lazy loaded list of vehicle information
      responses:
        "200":
          description: Lazy loaded vehicles
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/VehiclesInfoResponse"
        "401":
          description: user is not log in or authorization token is not valid
        "403":
          description: user has no rights to get vehicles

components:
  schemas:
    UUID:
      type: string
      example: 5bf5734123e5720001f0434f
      description: |
        Universal identifier. Currently it's MongoDb ObjectId.
        See details on [mongo db documentation](https://docs.mongodb.com/manual/reference/bson-types/#objectid).
    GUID:
      type: string
      example: 6F9619FF-8B86-D011-B42D-00C04FC964FF
      description: |
        Unique identifier. Currently it's MS SQL unique identifier type.
        See details on [sql server documentation](https://docs.microsoft.com/en-us/sql/t-sql/data-types/uniqueidentifier-transact-sql?view=sql-server-2017).

    ProgressBarStatus:
      deprecated: true
      type: string
      enum:
        - NORMAL # White progress bar.
        - WARNING # Orange progress bar.
        - ALERT # Red progress bar.

    MaintenanceLimitMetric:
      type: string
      enum:
        - KILOMETERS
        - DAYS
        - ENGINE_HOURS

    VehicleInfoMaintenanceLimit:
      description: Info about a vehicle maintenance limit.
      type: object
      additionalProperties: false
      properties:
        metric:
          $ref: "#/components/schemas/MaintenanceLimitMetric"
        status:
          # deprecated: true
          $ref: "#/components/schemas/ProgressBarStatus"
        currentValue:
          type: integer
          format: int32
          description: Current value to show in progress bar.
          example: 3000
          nullable: true
        thresholdValue:
          type: integer
          format: int32
          description: Threshold value to show in progress bar.
          example: 6341
          nullable: true
        percentage:
          type: number
          format: float
          description: Percentage to show in progress bar.
          example: 80.1
          nullable: true
        alertPercentage:
          type: integer
          format: int32
          description: Above this value show red progress bar
          example: 85
          nullable: true

    VehicleInfo:
      description: Information about a vehicle.
      type: object
      additionalProperties: false
      required:
        - id
      properties:
        id:
          $ref: "#/components/schemas/UUID"
        registrationNumber:
          type: string
          description: vehicle registration number
          example: "2H4 4585"
        vehicleId:
          type: string
          description: vehicle ID
          example: 548
        vehicleIdentificationNumber:
          type: string
          description: identification number of vehicle (VIN)
          example: "ZAR93700005192302"
        maintenanceLimit:
          $ref: "#/components/schemas/VehicleInfoMaintenanceLimit"
        maintenanceType:
          type: string
          example: "Servis"
          nullable: true
        note:
          type: string
          nullable: true
          example: "STK"
        outOfOrderFrom:
          type: string
          format: date-time
          example: "2018-10-24T12:10:01.000Z"
          nullable: true
        coreDriver:
          type: string
          example: "Standa Panda"
          nullable: true
        orderNumber:
          type: string
          example: "CA_4564564"
          nullable: true
        engineCapacity:
          type: integer
          format: int32
          example: 1200
        type:
          type: string
          description: Type of the vehicle
          example: Ford Transit 260S
        owner:
          type: string
          description: Owner of the vehicle
          example: DP
        rootCenter:
          type: string
          description: Root center of the vehicle
          example: 238120
        departmentCenter:
          type: string
          description: Department center of the vehicle
          example: 251200

    VehiclesInfoResponse:
      type: object
      additionalProperties: false
      properties:
        totalCount:
          type: integer
          format: int64
          description: Total number of rows (sum of rows on all pages).
            When the response is filtered, only total count
            of the rows matching the filters should be here.
          example: 120456
        result:
          type: array
          items:
            $ref: "#/components/schemas/VehicleInfo"

nswag configuration


  "runtime": "Default",
  "defaultVariables": null,
  "documentGenerator": {
    "fromDocument": {
      "json": "",
      "url": "../schema.yaml",
      "output": null,
      "newLineBehavior": "Auto"
    }
  },
  "codeGenerators": {
    "openApiToTypeScriptClient": {
      "className": "{controller}ApiClient",
      "moduleName": "",
      "namespace": "",
      "typeScriptVersion": 2.7,
      "template": "Fetch",
      "promiseType": "Promise",
      "httpClass": "Http",
      "withCredentials": false,
      "useSingletonProvider": false,
      "injectionTokenType": "OpaqueToken",
      "rxJsVersion": 5.0,
      "dateTimeType": "Date",
      "nullValue": "Undefined",
      "generateClientClasses": true,
      "generateClientInterfaces": true,
      "generateOptionalParameters": false,
      "exportTypes": true,
      "wrapDtoExceptions": false,
      "exceptionClass": "SwaggerException",
      "clientBaseClass": null,
      "wrapResponses": false,
      "wrapResponseMethods": [],
      "generateResponseClasses": true,
      "responseClass": "SwaggerResponse",
      "protectedMethods": [],
      "configurationClass": null,
      "useTransformOptionsMethod": false,
      "useTransformResultMethod": false,
      "generateDtoTypes": true,
      "operationGenerationMode": "MultipleClientsFromPathSegments",
      "markOptionalProperties": true,
      "generateCloneMethod": false,
      "typeStyle": "Class",
      "enumStyle": "Enum",
      "useLeafType": false,
      "classTypes": [],
      "extendedClasses": [
        "ApiClient",
        "MenuApiClient",
        "PolicyApiClient",
        "RegistrationCertificateApiClient",
        "EnumsApiClient",
        "EconomyApiClient",
        "BasicDataApiClient",
        "AccessoriesApiClient",
        "NotesApiClient",
        "InterventionsApiClient",
        "MaintenancesApiClient",
        "PermissionsApiClient",
        "QualificationsApiClient",
        "EntryCardsApiClient",
        "VehiclesApiClient",
      ],
      "extensionCode": "src/nswag-ext-class-stub",
      "generateDefaultValues": true,
      "excludedTypeNames": [],
      "excludedParameterNames": [],
      "handleReferences": true,
      "generateConstructorInterface": true,
      "convertConstructorInterfaceData": false,
      "importRequiredTypes": true,
      "useGetBaseUrlMethod": false,
      "baseUrlTokenName": "API_BASE_URL",
      "queryNullValue": "",
      "inlineNamedDictionaries": false,
      "inlineNamedAny": false,
      "templateDirectory": null,
      "typeNameGeneratorType": null,
      "propertyNameGeneratorType": null,
      "enumNameGeneratorType": null,
      "serviceHost": null,
      "serviceSchemes": null,
      "output": "src/ApiClient.ts",
      "newLineBehavior": "Auto"
    }
  }
}

tsconfig - Typescript - 3.9

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "declaration": true,
    "outDir": "./lib",
    "strict": true,
    "lib": ["dom", "es2015"]
  },
  "include": ["src"],
  "exclude": ["node_modules", "**/__tests__/*"]
}
cederstrom commented 2 years ago

@MirKml Did you ever find a solution for this?

MirKml commented 2 years ago

@cederstrom No, I think for fixing it's necessary to have good C# .NET knowledge and some understanding of nswag internals. And I haven't.

cederstrom commented 2 years ago

@RicoSuter I'm having the same issue. Do you have any tips on how to solve this? Thanks!

lahma commented 2 years ago

You could probably drop a custom template into use and add TS ignore via comment syntax maybe:

https://github.com/RicoSuter/NSwag/blob/master/src/NSwag.CodeGeneration.TypeScript/Templates/File.Header.liquid

Having template with same name in configured custom template directory (nswag.json configuration) should allow you to remove some checks. Not ideal, but less invasive change.

cederstrom commented 2 years ago

I solved this by setting handleReferences to false.

"documentGenerator": {
  "codeGenerators": {
    "openApiToTypeScriptClient": {
      "handleReferences": false
      ...
    }
  }
}
MirKml commented 2 years ago

@cederstrom It seems as good workaround when handleReferences isn't necessary. I will check if I can disable it. Thank you.