Live data from Hacker News

TypeScript Features to Avoid

executeprogram.com

41–50 of 212 posts

Re: TypeScript Features to Avoid

#41
post #29

As long as you are not using "const enums" JavaScript/TypeScript interop is not a real problem at all. The private keyword is obviously preferable to "#" in environments in which you are targeting older ES versions.

But const enums are gone after compiling. They're just namespaced constants that are inlined. I don't see how this could cause any problem.

Re: TypeScript Features to Avoid

#42
post #20

Earlier quoted context omitted.

This is how ES6 got classes. Developers wanted JS to be some other language they favored more. In that case specifically people were really hoping to make the language look and feel like Java, probably because they were trained in Java and couldn’t figure out functions as first class citizens.

The Java crowd indeed gave us god awful classes. But before that there were countless competing models for creating objects or object factories. Obviously, JavaScript is an object oriented language, too. You cannot escape that fact if you are determined to make the browser paint anything. Classes effectively solved the "How?" To pretend you don't need object orientation in JavaScript is really trying hard to make Jav…

> But before that there were countless competing models for creating objects or object factories.

Java and C# had object factories even though in those languages classes could not be avoided. People wanted classes because they could not figure how to program without them.

> To pretend…

Don’t use this or new in your code and suddenly a tremendous amount of your code is exposed as unnecessary superfluous vanity. That isn’t making the language into something else.

Re: TypeScript Features to Avoid

#43

> 1. Avoid Enums What? This is IMO bad advice. Having a sum type is quite handy for general type-checking, at least insofar as the type truly is an enumerated type (i.e. all possible values are known at design-time). There have been times when TypeScript enums have been indispensable to me when declaring the external interface to some client-facing API. Whatever the API boundary is, a sum type is useful. Also, TypeSc…

What are the advantages of enums over a string literal union? I can only see disadvantages.

Re: TypeScript Features to Avoid

#44
Const enums specifically are great, since they disappear on compile you can use them to internally document strings/numbers with verbose names/comments without the cost of a const variable that would appear after compilation.

As for the fact that types cannot simply be stripped out, I've found building using plain tsc and have the bundler target tsc's output directory. This separation is needed since most tools don't support TypeScript project references anyway which I find extremely useful for organizing internal modules.

Re: TypeScript Features to Avoid

#45
post #41
post #29

As long as you are not using "const enums" JavaScript/TypeScript interop is not a real problem at all. The private keyword is obviously preferable to "#" in environments in which you are targeting older ES versions.

But const enums are gone after compiling. They're just namespaced constants that are inlined. I don't see how this could cause any problem.

That's precisely the problem. It makes the enum invisible to JavaScript users.

Re: TypeScript Features to Avoid

#46

> 1. Avoid Enums What? This is IMO bad advice. Having a sum type is quite handy for general type-checking, at least insofar as the type truly is an enumerated type (i.e. all possible values are known at design-time). There have been times when TypeScript enums have been indispensable to me when declaring the external interface to some client-facing API. Whatever the API boundary is, a sum type is useful. Also, TypeSc…

Unfortunately TypeScript's enums have various shortcomings compared to powerful sum types in languages like Rust:

- https://stackoverflow.com/questions/40275832/typescript-has-...

- https://github.com/microsoft/TypeScript/issues/32690

In a TS codebase I'm currently working on, we have the policy of never using "plain" TS enums. Instead, we have a tool that generates our own enum objects using a schema and a generator script for the cases where we want "rich" enums. For other use cases, we use string unions a lot (in combination with a helper function that allows exhaustive matching).

Re: TypeScript Features to Avoid

#47
post #40

> 1. Avoid Enums What? This is IMO bad advice. Having a sum type is quite handy for general type-checking, at least insofar as the type truly is an enumerated type (i.e. all possible values are known at design-time). There have been times when TypeScript enums have been indispensable to me when declaring the external interface to some client-facing API. Whatever the API boundary is, a sum type is useful. Also, TypeSc…

The TypeScript ecosystem is bigger than just the official compiler, though. Many projects use alternative compilers like esbuild or @babel/preset-typescript for their main pipeline and only use the official TypeScript compiler as a typechecker (with `--noEmit`, during CI). It's true that enums are harder to support for alternative compilers. Especially `const enum` seems to be harder.

> It's true that enums are harder to support for alternative compilers.

As long as it is supported — and at least esbuild does, who cares (as a user). Should I start avoiding every JS feature that is hard to implement in alternative JS runtimes?

Re: TypeScript Features to Avoid

#48
post #23

I disagree with this. We have a reasonably large Angular application that is only going to get much bigger (hard to define what that means ... big telephony app with tens of thousands of customers). I am the lead and architect. We use enums and private keywords. With the private keywords, all I care about is that it is logically correct. We use private when things are truly private, i.e. they are only called from wit…

> I honestly don't care what this transpiles down to, the point for us at least is not to make things "truly private" (good luck with that in JavaScript). It's simply to compiler-enforce rules. It’s not just JavaScript. With reflection in C# and Java, you can mess around with private variables from outside the classes. For Java, this can have some pretty interesting results, such as 2+2 being equal to 5 .[0] The whol…

> With reflection, you can mess around with private variables from outside the classes.

Worth mentioning that you can disallow reflection via the security manager, at least in earlier versions of the JVM.

Re: TypeScript Features to Avoid

#49
This whole thing feels basically grounded in purity over practicality. In general it's a good idea to write idiomatic TypeScript. Even when I agree with the given recommendations, the given reasons don't seem like the strongest ones.

I most strongly disagree with the recommendation against enums. Realistically, you will probably never run into a compiler bug from enum emit; maybe something like this might happen with a very complicated runtime feature, but enum emit is dead-simple and hard to get wrong (at least if your toolchain has any tests at all, which it presumably should). And they're generally convenient and fill a useful niche, especially numeric enums with implicitly assigned values. (I'm also curious what the article's authors think of const enums.)

Namespaces have been soft-deprecated, modules are pretty much just better, and so I quite agree that you shouldn't use them, though I'm not sure the risk of compiler bugs is the most compelling argument against. (It is more compelling than with enums, since the required code transformations are much less trivial.)

Decorators, especially with metadata, facilitate lots of useful things that otherwise just aren't possible in TypeScript. It's also the case (though the authors seem unaware of this) that they will never be standardized in the current form that TypeScript has them, because they were based on an earlier version of the design that has since been pretty explicitly rejected. The risk isn't that decorators are never standardized; if that happens then TypeScript will just keep the current design forever and things will be mostly fine. The risk is that they get standardized in an incompatible form and then you have an interesting migration ahead of you. TC39 won't do this lightly, but no one knows exactly what the future holds. So it is a tradeoff to think carefully about, though in the end reasonable people will disagree.

# vs. private is mostly a matter of style/taste, with two exceptions. First, if you have any code on your page that you don't trust not to be doing weird things, strongly consider #, since it provides protection against corruption of internal state. Second, if you have to support older browsers that don't support #, then don't use it; the compiler can downlevel it, but only at significant code-size and performance cost that you don't want to pay (and debugging it in the browser will also be annoying).

Do the authors also disfavor parameter properties? Those also require emit beyond just stripping types, but are super-convenient and useful and don't really conceptually complicate things.

Incidentally, the feature at the top of my own list of "TypeScript features to avoid" (other than namespaces and other soft-deprecated features) is something entirely different: conditional types. Most other advanced type-system features behave reasonably predictably most of the time, but conditional types are very demanding of maintainers' knowledge of fiddly type-system details. I'm not saying it's never worth it (and in particular the built-in utility types are usually fine even though they're conditional under the hood), but whenever possible I try to reach for something else.

Re: TypeScript Features to Avoid

#50

> 1. Avoid Enums What? This is IMO bad advice. Having a sum type is quite handy for general type-checking, at least insofar as the type truly is an enumerated type (i.e. all possible values are known at design-time). There have been times when TypeScript enums have been indispensable to me when declaring the external interface to some client-facing API. Whatever the API boundary is, a sum type is useful. Also, TypeSc…

What are the advantages of enums over a string literal union? I can only see disadvantages.

In some cases you can use it to define string arguments to an external library. Maybe table names to an ORM or a well-known file path. This helps because you get autocomplete from typing `MyEnum.` and seeing options, even though the external function takes a plain string.
Post reply on HN