Enums is going to make your TypeScript code not work in a future where TypeScript code can be run with Node.js or in browser when typings are added to JavaScript[1]
Enums results in runtime code and in most cases you really want type enums. Use `type State = "Active" | "Inactive"` and so on instead. And if you really want an closed-ended object use `const State = { Active: 1, Inactive: 0 } as const`
All of the examples in the article can be achieved without enums. See https://www.typescriptlang.org/play/?#code/PTAEFEA8EMFsAcA2B...
Apparently they're planning on adding a tsconfig option to disallow these Node-incompatible features as well [1].
Using this limited subset of TS also allows your code to compile with Bloomberg's ts-blank-space, which literally just replaces type declarations with whitespace [2].
FYI, this is now. Node 23.6 will just run typescript files than can have their types stripped https://nodejs.org/en/blog/release/v23.6.0#unflagging---expe....
There is a seperate --experimental-transform-types flag which'll also transform for enums, but no idea if they ever intend to make this not experimental or unflagged.
The only other twist to import syntax is marking type-only imports with the type keyword so that those imports can be completely ignored by simple type removers like Node's. You can turn that check on today in Typescript's compile options with the verbatimModuleSyntax [1] flag, or various eslint rules.
[1] https://www.typescriptlang.org/tsconfig/#verbatimModuleSynta...
its 2025 and node is finally good :)
https://github.com/tc39/proposal-type-annotations/commits/ma...
export const MyEnumMapping = {
active: 0,
inactive: 1
} as const
export type MyEnum = typeof MyEnumMapping[keyof typeof MyEnumMapping];
So you have the names exposed, but the underlying type is the number.Personally I am definitely not skilled enough at typescript to come up with this on my own before seeing this thread so this was not even an option until now.
type MyEnum = {
active: 0;
inactive: 1;
}
const MyEnum: MyEnum = {
active: 0,
inactive: 1,
}
const showAge = MyEnum.active;
const showPets = MyEnum.inactive;
It's slightly more duplication, but a lot more readable (imo) to those unfamiliar to utility types. TypeScript also enforces keeping them in sync.I'm able to do that just fine in VS Code / Cursor.
I set up a union like this:
export type TestUnion = 'foo' | 'bar' | 'baz';
Then use it in another file like this: const bar: TestUnion = 'bar';
const barString: string = 'bar';
If I select 'bar' from the type and choose "Go to references", it shows me the `const bar` line, but not the `const barString` line, which is what I would expect.It really says a lot about how immature it is especially for backend and just by even hearing the complaints about TypeScript 'enums' tells me all I need to know.
So what other foot-guns have the JS / TS ecosystem have hidden?
How is that the conclusion you reach? The proposal you link says types will be treated like comments by the runtime, so it's not about adding types that will be used in the runtime (which begs the question, why even add it? But I digress), but about adding types that other tooling can use, and the runtime can ignore.
So assuming the runtime will ignore the types, why would using enums specifically break this, compared to any other TypeScript-specific syntax?
If you ask me, both features have been de facto deprecated for ages now.
The future has been here for a while.
Seems weird to me to decide you're OK with the build step and all the other complexity TS adds, but using enums is too much, because maybe in the future JS runtimes might be able to strip away types for you without a build-step.
But we all have different constraints and use cases, I suppose it does make sense for what you're building.
Maybe library compatibility?
My first reaction is that this just further fractures the ecosystem, where some codebases/libraries will have TS that is required to be compiled and some will not, adding a third kind of TS/JS code that's out there.
We’re not talking about the distant future. Node shipped its first version supporting type stripping six months ago.
> Since Node.js is only removing inline types, any TypeScript features that involve replacing TypeScript syntax with new JavaScript syntax will error, unless the flag --experimental-transform-types is passed.
> The most prominent features that require transformation are:
> Enum > namespaces > legacy module > parameter properties