Current behavior: nullable C# types (`string?`, `int?`, `T?` on a reference type) lower to TypeScript as `T | null` with a default of `null`. This is deliberate — see the `null vs undefined` memo — because APIs crossing the TS boundary benefit from the distinction between "this field is explicitly absent" (null) and "this field was not provided" (undefined).
However, some APIs (React props, JSON bodies that omit absent fields, Hono request schemas) want `undefined` semantics — the `param?: T` form where the key simply isn't set. Today there's no way to opt into that shape.
Goal
Introduce a `[Optional]` attribute that opts a parameter or property into the `param?: T` / `prop?: T` form instead of the default `param: T | null = null`.
Scope
Default still wins
This is opt-in. The default stays `T | null = null` for safety at the API boundary.
Part of #14.
Current behavior: nullable C# types (`string?`, `int?`, `T?` on a reference type) lower to TypeScript as `T | null` with a default of `null`. This is deliberate — see the `null vs undefined` memo — because APIs crossing the TS boundary benefit from the distinction between "this field is explicitly absent" (null) and "this field was not provided" (undefined).
However, some APIs (React props, JSON bodies that omit absent fields, Hono request schemas) want `undefined` semantics — the `param?: T` form where the key simply isn't set. Today there's no way to opt into that shape.
Goal
Introduce a `[Optional]` attribute that opts a parameter or property into the `param?: T` / `prop?: T` form instead of the default `param: T | null = null`.
Scope
Default still wins
This is opt-in. The default stays `T | null = null` for safety at the API boundary.
Part of #14.