orval icon indicating copy to clipboard operation
orval copied to clipboard

Additional properties causing TS error. "Property is not assignable to index type."

Open Tymek opened this issue 2 years ago • 5 comments

What are the steps to reproduce this issue?

Create schema with typed additionalProperties

        "additionalProperties": {
          "type": "string",
          "example": "something"
        },

Discussed in https://github.com/anymaniax/orval/discussions/599

Originally posted by Tymek September 30, 2022 When I have additional properties (like in this source file), generated type has issues like for example Property 'remoteAddress' of type 'string | undefined' is not assignable to 'string' index type 'string'. because of index type [key: string]: string;.

Is there a way of making it work with TypeScript?

More details

From schema JSON:

...
      "sdkContextSchema": {
        "description": "The Unleash context as modeled in client SDKs",
        "type": "object",
        "additionalProperties": {
          "type": "string",
          "example": "top-level custom context value"
        },
        "required": [
          "appName"
        ],
        "properties": {
          "appName": {
            "type": "string",
            "minLength": 1,
            "example": "My cool application."
          },
          "currentTime": {
            "type": "string",
            "format": "date-time",
            "example": "2022-07-05T12:56:41+02:00"
          },
          "environment": {
            "type": "string",
            "deprecated": true
          },
          "properties": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "example": {
              "customContextField": "this is one!",
              "otherCustomField": "3"
            }
          },
...
        }
      },
...

I get output like so:

/**
 * Generated by orval v6.10.2 🍺
 * Do not edit manually.
 * Unleash API
 * OpenAPI spec version: 4.15.1
 */
import type { SdkContextSchemaProperties } from './sdkContextSchemaProperties';

/**
 * The Unleash context as modeled in client SDKs
 */
export interface SdkContextSchema {
  appName: string;
  currentTime?: string;
  /** @deprecated */
  environment?: string;
  properties?: SdkContextSchemaProperties;
  remoteAddress?: string;
  sessionId?: string;
  userId?: string;
  [key: string]: string;
}

Tymek avatar Sep 30 '22 09:09 Tymek

Relevant code: https://github.com/anymaniax/orval/blob/f3928e184e9e44e686162e2eda194092e8a564ac/src/core/getters/object.ts#L104

What's the preferred way to fix it? How about checking if object also has properties of other type, and changing to any if it does?

Are community PRs welcome?

Tymek avatar Sep 30 '22 14:09 Tymek

sure for PR but I am not just that just transform it to any is a good solution tho

anymaniax avatar Sep 30 '22 14:09 anymaniax

Right. Even resolvedValue.value | <other types from properties> is not strictly correct.

Only way I know to make this work is to switch to Intersection Types, but that will export type instead of interface..

Tymek avatar Sep 30 '22 14:09 Tymek

having the same issue

michinger avatar May 23 '24 10:05 michinger

As a temporary workaround while this issue isn't fixed, this afterAllFilesWrite bash script will add //ts-no-check to all the generated files so that the error is suppressed; obviously not ideal to supress errors, but it will do the trick while the issue isn't fixed.

#!/bin/bash

# Check if at least one file is provided as an argument
if [ $# -eq 0 ]; then
  exit 0
fi

fixFile() {
  local file_path="$1"
  # Read the file content
  content=$(cat "$file_path")

  # Prepend the @ts-nocheck directive
  echo -e "// @ts-nocheck\n$content" > "$file_path"
}

# Loop through all provided files
for path in "$@"
do
  # Check if the file exists and is a regular file
  if [ -f "$path" ]; then
    fixFile "$path"
    # Read the file content
    content=$(cat "$file")

    # Prepend the @ts-nocheck directive
    echo -e "// @ts-nocheck\n$content" > "$file"
  # Otherwise, check if it's a directory - !NOTE! not recursive
  elif [ -d "$path" ]; then
    for file in "$path"/*.ts; do
      fixFile "$file"
    done
  fi
done

# Run linting - or any other afterAllFilesWrite commands you want
yarn lint

PedroPerpetua avatar Jul 09 '24 13:07 PedroPerpetua