Feature Request/Enhancement
Nitrogen currently fails to generate a spec when a TypeScript type contains never, with:
❌ Failed to generate spec for Entity! Error: The TypeScript type "never" cannot be resolved - is it imported properly? Make sure to import it properly using fully specified relative or absolute imports, no aliases.
❌ No specs found in Entity.nitro.ts!
This makes it impossible to use the standard TypeScript pattern for discriminated/exclusive unions, where optional never properties are used to prevent excess-property leakage between union members, for example:
interface Rect {
width: number;
height: number;
}
interface Circle {
radius: number;
}
type Shape = Rect | Circle;
interface Entity {
shape: Shape;
}
For C++, this correctly generates:
struct Entity final {
public:
std::variant<Rect, Circle> shape SWIFT_PRIVATE;
};
which is exactly what I want. However, in plain TypeScript, this doesn't actually enforce exclusivity: an object like:
shape: { width: 100, height: 200, radius: 50 }
is accepted without error, since Shape is a union of object types and TS structurally allows extra properties in some contexts (and definitely doesn't reject this in a variable of type Shape built inline in certain positions).
The standard TS workaround for this is to add mutually exclusive never properties:
interface Rect {
width: number;
height: number;
radius?: never;
}
interface Circle {
radius: number;
width?: never;
height?: never;
}
This correctly makes Shape behave as an exclusive union in TypeScript, but Nitrogen fails to generate a spec for it, with the error shown above.
Expected behavior
Optional never properties should be ignored when generating the C++/Swift/Kotlin spec, rather than causing a hard error. They carry no runtime value and exist purely to help TypeScript enforce exclusivity between union members.
Environment
- nitrogen / react-native-nitro-modules version:
"0.35.3"
Are there any existing workarounds?
Not really a functional one: the ?: never pattern is the standard TypeScript idiom for enforcing mutual exclusivity between union members (see the Shape/Rect/Circle example above), and it's necessary because plain union types like Rect | Circle don't actually prevent excess/overlapping properties from being accepted. Without never, TypeScript happily accepts an object like { width: 100, height: 200, radius: 50 } as a valid Shape, which defeats the purpose of the union.
The only "workaround" is to not enforce exclusivity in TypeScript at all (drop the never fields), and instead do manual runtime validation of the shape's fields elsewhere but that reintroduces exactly the ambiguity the union type was meant to prevent, and gives up compile-time safety.
Additional information
Feature Request/Enhancement
Nitrogen currently fails to generate a spec when a TypeScript type contains never, with:
This makes it impossible to use the standard TypeScript pattern for discriminated/exclusive unions, where optional never properties are used to prevent excess-property leakage between union members, for example:
For C++, this correctly generates:
which is exactly what I want. However, in plain TypeScript, this doesn't actually enforce exclusivity: an object like:
is accepted without error, since
Shapeis a union of object types and TS structurally allows extra properties in some contexts (and definitely doesn't reject this in a variable of typeShapebuilt inline in certain positions).The standard TS workaround for this is to add mutually exclusive
neverproperties:This correctly makes
Shapebehave as an exclusive union in TypeScript, but Nitrogen fails to generate a spec for it, with the error shown above.Expected behavior
Optional
neverproperties should be ignored when generating theC++/Swift/Kotlinspec, rather than causing a hard error. They carry no runtime value and exist purely to help TypeScript enforce exclusivity between union members.Environment
"0.35.3"Are there any existing workarounds?
Not really a functional one: the
?: neverpattern is the standard TypeScript idiom for enforcing mutual exclusivity between union members (see theShape/Rect/Circleexample above), and it's necessary because plain union types likeRect | Circledon't actually prevent excess/overlapping properties from being accepted. Withoutnever, TypeScript happily accepts an object like{ width: 100, height: 200, radius: 50 }as a valid Shape, which defeats the purpose of the union.The only "workaround" is to not enforce exclusivity in TypeScript at all (drop the never fields), and instead do manual runtime validation of the shape's fields elsewhere but that reintroduces exactly the ambiguity the union type was meant to prevent, and gives up compile-time safety.
Additional information