feat: type only namespaces - #174
Open
m-rutter wants to merge 1 commit into
Open
Conversation
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
marked this pull request as ready for review
July 8, 2026 16:40
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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-namespacesand 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.