Skip to content

feat: type only namespaces - #174

Open
m-rutter wants to merge 1 commit into
mainfrom
type-only-namespaces
Open

feat: type only namespaces#174
m-rutter wants to merge 1 commit into
mainfrom
type-only-namespaces

Conversation

@m-rutter

@m-rutter m-rutter commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

A problem with the existing codegen is it uses namespaces, a precursor feature to esm module specific to typescript that gets compiled into a iife with an object export. This does not work with certain modern tooling such as node's strip types support which allows you to evaluate typescript modules provided you don't use any non-erasable typescript only features. Namespaces with runtime values, such as string consts, cannot be erased.

The role of namespaces in this codegen is to... well provide namespaces mirroring avro namespaces and avoiding name collisions across avro namespaces. Typescript namespaces were actually a perfect fit for avro namespaces, but unfortunately tooling is moving away from typescript namespaces. The idiomatic way of fixing this in typescript today would be to create a separate esm module (file) per namespace, but that is a major change and would require a lot of refactoring.

Instead what I've done is is changed the codegen to be functionally identical by splitting the codegen into two parts. Firstly we keep namespaces but make them type only exports - meaning that they are erasable by node's strip types feature. Secondly all value constants get exported inside of an object literal of the same name as the namespace. This functionally works identically to the old codegen from the pov of the consumer, but with the one caveat that you cannot use typescript enums in this mode.

I've called the mode experimental-type-only-namespaces and defaulted it to false, but if we were to ever release a semver breaking change I would argue this should be the new default.

The longer term path is probably still moving towards having a esm module (file) per avro namespace.

A problem with the existing codegen is it uses namespaces, a precusor
feature to esm module specific to typescript that gets compiled into a
iife with an object export. This does not work with certain modern
tooling such as node's strip types support which allows you to evaluate
typescript modules provided you don't use any non-erasable typescript
only features. Namespaces cannot be erased.

The purpose of namespaces in this codegen is to... well provide
namespaces mirroring avro namespaces and avoiding name collisions across
avro namespaces. The idiomatic way of fixing this in typescript today
would be to create a seperate esm module per namespace, but that is a
major change and would require a lot of refactoring.

Instead what I've done is is changed the codegen to be functionally
identical by splitting the codegen into two parts. Firstly we keep
namespaces but make them type only exports - meaning that they are
erasable by node's strip types feature. Secondly all value constants get
exported inside of an object literal of the same name as the namespace.
This functionally works identically to the old codegen from the pow of
the consumer, but with the one cavet that you cannot use typescript
enums in this mode.

I've called the mode `experimental-type-only-namespaces` and defaulted
it to false, but if we were to ever release a semver breaking change I
would aruge this should be the new default.

The longer term path is probably still moving towards having a esm
module per avro namespace.
@m-rutter
m-rutter marked this pull request as ready for review July 8, 2026 16:40
@m-rutter
m-rutter requested a review from a team as a code owner July 8, 2026 16:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant