What happens
When a discriminated union uses a boolean literal as the tag (ok: true | false), the generated SDK output emits ok: true on both branches. The false literal is lost.
Versions
- typia: 11.0.3
- @nestia/sdk: 10.0.2
- nestia: 10.0.2
- typescript: 5.9.3
Repro
Source controller return type:
| { ok: false; error: { code: string } }
| { ok: true; code: string; data: { id: string } }
Generated SDK output:
| { ok: true; error: { code: string } } // wrong, should be ok: false
| { ok: true; code: string; data: { id: string } }
Both branches end up with ok: true. Client-side narrowing via if (res.ok) is broken because both branches are now structurally compatible on the discriminator.
Minimal sample
NestJS controller:
@TypedRoute.Get('me')
async getMe(): Promise<
| { ok: false; error: { code: 'X' } }
| { ok: true; code: 'X'; data: number }
> {
return { ok: true, code: 'X', data: 1 }
}
Run nestia sdk. Inspect generated me/index.ts. Both Output union members will have ok: true.
Workaround
String tag survives. Replace boolean discriminator with string:
| { kind: 'error'; ok: false; ... }
| { kind: 'success'; ok: true; ... }
kind round-trips fine. Only ok: true | false collapses.
Or use property existence on the client ('data' in res) instead of res.ok.
Where I think the bug lives
I have not traced it all the way, but the symptom looks like boolean literal information being dropped during metadata flattening. String literals in the same position keep both members. So the issue seems specific to how boolean atomics are stored or re-emitted.
Happy to send a PR if someone can point at the right file.
What happens
When a discriminated union uses a boolean literal as the tag (ok: true | false), the generated SDK output emits ok: true on both branches. The false literal is lost.
Versions
Repro
Source controller return type:
Generated SDK output:
Both branches end up with ok: true. Client-side narrowing via if (res.ok) is broken because both branches are now structurally compatible on the discriminator.
Minimal sample
NestJS controller:
Run nestia sdk. Inspect generated me/index.ts. Both Output union members will have ok: true.
Workaround
String tag survives. Replace boolean discriminator with string:
kind round-trips fine. Only ok: true | false collapses.
Or use property existence on the client ('data' in res) instead of res.ok.
Where I think the bug lives
I have not traced it all the way, but the symptom looks like boolean literal information being dropped during metadata flattening. String literals in the same position keep both members. So the issue seems specific to how boolean atomics are stored or re-emitted.
Happy to send a PR if someone can point at the right file.