Skip to content

queryParamType returns unknown for OAS 3.1 nullable array union type ["array", "null"] #303

@benjamineckstein

Description

@benjamineckstein

Bug report (follow-up to #299)

After the fix in #301, array query params with a 3.1 nullable union type are still typed as unknown and serialized with set() instead of append().

Root cause

queryParamType (client.ts) handles the OAS 3.1 null-union form like this:

if (Array.isArray(s.type)) {
  const nonNull = (s.type as string[]).filter((t) => t !== 'null')
  if (nonNull.length === 1) return primitiveToTs(nonNull[0])  // <-- primitiveToTs('array') === 'unknown'
  return 'string'
}

When the type is ["array", "null"], nonNull is ["array"], and primitiveToTs("array") returns "unknown" (array is not a primitive). The param therefore misses the type === 'array' branch below and the append()-loop serialization path is never reached.

Minimal spec

parameters:
  - name: "ids[]"
    in: query
    schema:
      type:
        - array
        - "null"
      items:
        type: integer
    style: form
    explode: true

This is the OAS 3.1 equivalent of schema: { type: array, items: { type: integer }, nullable: true }.

Generated output (current)

"ids[]"?: unknown
// ...
searchParams.set("ids[]", String(params["ids[]"]))

Expected output

"ids[]"?: number[]
// ...
if (params["ids[]"] != null) { for (const v of params["ids[]"]) searchParams.append("ids[]", String(v)) }

Suggested fix

In the Array.isArray(s.type) branch, check if the single non-null type is "array" before falling through to primitiveToTs:

if (Array.isArray(s.type)) {
  const nonNull = (s.type as string[]).filter((t) => t !== 'null')
  if (nonNull.length === 1) {
    if (nonNull[0] === 'array') {
      // Nullable array — treat identically to the non-nullable array branch below
      const items = (s as OpenAPIV3_1.ArraySchemaObject).items as SchemaObject | undefined
      if (items !== undefined && (items.type === 'integer' || items.type === 'number')) return 'number[]'
      return 'string[]'
    }
    return primitiveToTs(nonNull[0])
  }
  return 'string'
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions