nitro icon indicating copy to clipboard operation
nitro copied to clipboard

Optional variant/union fields don't use TypeScript type name in generated Swift enums

Open szymonograbek opened this issue 2 months ago • 0 comments

What happened?

While working on react-native-health, I noticed that when an optional field is a variant (i.e., a filter field that is a large union of possible filters), the generated Swift enum name doesn't match the TypeScript type name.

I found a workaround: if you create another union that explicitly includes undefined with the optional field, it generates correctly.

In the example below nitrogen doesn't generate the name based on the type name (Variant_DateFilter_DurationFilter for the optional DateOrDurationFilter field). For the WorkaroundFilter the generated name is correct and the file contents are the same as Variant_DateFilter_DurationFilter.

This has became a problem for me as I've hit the file name limits when the generated name was too long for Swift to compile.

Nitrogen CLI logs (with --logLevel="debug")

🔧  Loading nitro.json config...
🚀  Nitrogen 0.0.1 runs at ~/werk/nitro-modules-reproduction/reproduction
    🔍  Nitrogen found 1 spec in ./src/specs
⏳  Parsing Example.nitro.ts...
    ⚙️   Generating specs for HybridObject "Example"...
        shared: Generating C++ code...
          C++: Creating HybridExampleSpec.hpp...
          C++: Creating HybridExampleSpec.cpp...
          C++: Creating OptionsWithRequired.hpp...
          C++: Creating DateFilter.hpp...
          C++: Creating DurationFilter.hpp...
          C++: Creating OptionWithWorkaround.hpp...
          C++: Creating OptionWithOptional.hpp...
        ios: Generating Swift code...
          Swift: Creating HybridExampleSpec.swift...
          Swift: Creating OptionsWithRequired.swift...
          Swift: Creating DateOrDurationFilter.swift...
          Swift: Creating DateFilter.swift...
          Swift: Creating DurationFilter.swift...
          Swift: Creating OptionWithWorkaround.swift...
          Swift: Creating WorkaroundFilter.swift...
          Swift: Creating OptionWithOptional.swift...
          Swift: Creating Variant_DateFilter_DurationFilter.swift...
          Swift: Creating HybridExampleSpec_cxx.swift...
          C++: Creating HybridExampleSpecSwift.hpp...
          C++: Creating HybridExampleSpecSwift.cpp...
        android: Generating Kotlin code...
          Kotlin: Creating HybridExampleSpec.kt...
          C++: Creating JHybridExampleSpec.hpp...
          C++: Creating JHybridExampleSpec.cpp...
          Kotlin: Creating OptionsWithRequired.kt...
          C++: Creating JOptionsWithRequired.hpp...
          Kotlin: Creating DateOrDurationFilter.kt...
          C++: Creating JDateOrDurationFilter.hpp...
          C++: Creating JDateOrDurationFilter.cpp...
          Kotlin: Creating DateFilter.kt...
          C++: Creating JDateFilter.hpp...
          Kotlin: Creating DurationFilter.kt...
          C++: Creating JDurationFilter.hpp...
          Kotlin: Creating OptionWithWorkaround.kt...
          C++: Creating JOptionWithWorkaround.hpp...
          Kotlin: Creating WorkaroundFilter.kt...
          C++: Creating JWorkaroundFilter.hpp...
          C++: Creating JWorkaroundFilter.cpp...
          Kotlin: Creating OptionWithOptional.kt...
          C++: Creating JOptionWithOptional.hpp...
          Kotlin: Creating Variant_DateFilter_DurationFilter.kt...
          C++: Creating JVariant_DateFilter_DurationFilter.hpp...
          C++: Creating JVariant_DateFilter_DurationFilter.cpp...
⛓️   Setting up build configs for autolinking...
    Creating autolinking build setup for ios...
          Ruby: Creating NitroReproduction+autolinking.rb...
          C++: Creating NitroReproduction-Swift-Cxx-Bridge.hpp...
          C++: Creating NitroReproduction-Swift-Cxx-Bridge.cpp...
          C++: Creating NitroReproduction-Swift-Cxx-Umbrella.hpp...
    Creating autolinking build setup for android...
          Cmake: Creating NitroReproduction+autolinking.cmake...
          Gradle: Creating NitroReproduction+autolinking.gradle...
          C++: Creating NitroReproductionOnLoad.hpp...
          C++: Creating NitroReproductionOnLoad.cpp...
          Kotlin: Creating NitroReproductionOnLoad.kt...
🎉  Generated 1/1 HybridObject in 0.8s!
💡  Your code is in ./nitrogen/generated

Nitro Specs (.nitro.ts)

import type { HybridObject } from "react-native-nitro-modules";

interface DateFilter {
  startDate?: Date;
  endDate?: Date;
}

interface DurationFilter {
  duration: number;
}
type DateOrDurationFilter = DateFilter | DurationFilter

type WorkaroundFilter = DateOrDurationFilter | undefined

interface OptionsWithRequired {
  filters: DateOrDurationFilter
}

interface OptionWithOptional {
  filters?: DateOrDurationFilter 
}

interface OptionWithWorkaround {
  filters?: WorkaroundFilter 
}

export interface Example extends HybridObject<{ios: "swift", android: "kotlin"}> {
  process(options: OptionsWithRequired, workaround: OptionWithWorkaround, optionOptional?: OptionWithOptional, ): number
}

Nitro Modules Version

0.29.8

Nitrogen Version

0.29.8

Operating system

MacOS

Additional information

szymonograbek avatar Oct 08 '25 14:10 szymonograbek