Live data from Hacker News

TypeScript Features to Avoid

executeprogram.com

21–30 of 212 posts

Re: TypeScript Features to Avoid

#21

tldr: avoid features in TypeScript which must emit runtime code when compiling to JavaScript - that is, any TypeScript-exclusive feature that’s not type annotations. Honestly most of these features are really useful, and as someone who never wants to work in raw JavaScript, I wish they were just added to JavaScript instead. Why shouldn’t JavaScript have enums, namespaces, private modifiers which aren’t #, and decorat…

I'd go further. There's no strong argument for why code-gen is bad. Why is a compilation process that is simply "remove type annotations" inherently better than one that emits code, or does code transformations, other than just personal preference, aesthetics, or simplicity? About the only positive that is qualitatively different is the simplicity of comparing the output to the input. But for someone building a large…

I think TypeScript loosely mapping to JS is important if just because JS sourcemaps suck, like they're so often randomly ignored in callstacks etc. And JS semantics are so subtle it makes transpiling any other language a pain.

But this doesn't justify removing every codegen feature. Namespaces and enums won't make your code less reasonable, and moreover they're just syntax sugar, they don't change actual JS semantics.

Re: TypeScript Features to Avoid

#22
What I like about TypeScript is that all these features are optional, declaring that they should be avoided is going too far, bus so would be saying that you should always use all features of a language if it could apply.

Everything has its place, and for allot of the features of TypeScript I think they are designed to be useful when you have a large number of developers working on incredibly large codebases.

I suppose in some ways it's like C++, you can decide to fully embrace all of its features, or code in a much more C like way, just taking advantage of classes.

It comes down to personal/team preference, what works for you.

Personally with TypeScript I'm inclined to code in a "closer to JavaScript" way (but taking full advantage of types obviously), but would happily work in whatever style was prevailing in the project.

Re: TypeScript Features to Avoid

#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 within the same class and don't need to be made visible to the view template or outside of the class. 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. We also have ESLint to ensure that our private fields are all below the public ones to keep things nice and neat.

I also enforce that we actually make things as public although that isn't needed, and I enforce returning void.

So instead of:

someMethod() {}

I have us use:

public someMethod(): void {}

Just to state what you intend.

I realize "I don't care what this transpiles down to" might really irk some people, but I really don't. In our C# back-end I am much more strict about this stuff, but in JS at the moment given the standardization of the #private fields and the fact I consider them really ugly, I honestly don't care. Just give me a clean code base that enforces we can't reference private fields and methods from our templates.

For enums, I recently wrote a method that does exactly what this article says not to do, use it for GET, POST, and PUT.

What would be a cleaner way to write this? If it has to be refactored into something much "uglier" I don't think I'd prefer it.

    this.downloadService.fileWithProgress(url, RequestType.post, ActionType.download, body)
This is a service I wrote that handles real-time progress (i.e. show an accurate progress bar when downloading files). I think this is clean and logical.

Re: TypeScript Features to Avoid

#24

tldr: avoid features in TypeScript which must emit runtime code when compiling to JavaScript - that is, any TypeScript-exclusive feature that’s not type annotations. Honestly most of these features are really useful, and as someone who never wants to work in raw JavaScript, I wish they were just added to JavaScript instead. Why shouldn’t JavaScript have enums, namespaces, private modifiers which aren’t #, and decorat…

I'd go further. There's no strong argument for why code-gen is bad. Why is a compilation process that is simply "remove type annotations" inherently better than one that emits code, or does code transformations, other than just personal preference, aesthetics, or simplicity? About the only positive that is qualitatively different is the simplicity of comparing the output to the input. But for someone building a large…

I see the next to zero codegen in typescript as a strategy: it removes all discutions about languages features besides typing, guarantees next to zero issues in production in case of code generation bug, making compiler deliveries safe and avoid need of coordination in toolchain.

Re: TypeScript Features to Avoid

#25
Despite the large amount of criticism in the comments here I think that the point the article makes here is pretty valid.

The described features are not what TypeScript itself wants to be, and I think if it wasn't for backwards compatibility the team would remove some of them.

IIRC namespaces as well as the `import = ` syntax come from a time where ESM wasn't a thing yet but a module system was very much needed. So now that ESM can be used pretty much everywhere namespaces can be avoided and therefore reduce the learning surface of TypeScript.

Enums IMO have no advantage over union types with string literals, e.g. `type Status = 'fulfilled' | 'pending' | 'failed'`. They map way better to JSON and are generally easier to understand, while still benefiting from type safety and typo protection.

Well the private keyword is kind of like namespaces in that it came from a time where the feature was needed/wanted, but the EcmaScript spec was not moving fast enough. So they made their own version of it which is now obsolete.

And for decorators, IIRC the decorator spec has already moved on and TypeScript's implementation is no longer up to date with it. And the spec itself is only stage 2 as mentioned in the article, so I wouldn't recommend using decorators either, you will face breaking changes with them some time in the future.

Furthermore, it is far more likely that you run into trouble when using one of these features with a compiler that is not TSC, e.g. esbuild or Babel. Decorators have never been working all that well with the Babel plugin. Enums are probably fine here.

Re: TypeScript Features to Avoid

#26

My problem with enums isn’t so much that it breaks type-level extension, it’s that it breaks structural typing. I don’t particularly care what the generated JS looks like when I do all my work in TS, but I do care that the type system of the language I do work in works in a consistent manner.

I find string enums useful when I want nominal typing. However, I do think that it is a little confusing when most of the type system is structural, except for string enums. What complicates things further is that any number can be assigned to a number enum without casting, which I understand is so enums can represent bitfields (e.g. so Permissions.Read | Permissions.Write is still of type Permissions instead of number), but I wish numeric enums worked the same as string enums and doing bitwise operations on these enums would return the enum type and not a type-erased `number`.

I mostly agree with the rest of the article’s recommendations, but don’t fully agree with their reasoning.

- Yes, namespaces should be avoided, but not because they generate extra code. Namespaces are not recommended anymore and modules (actual JS modules not TS’ `module`) is the recommended approach now.

- Yep, private fields are better for ensuring a field is truly private.

- I think decorators are fine to use if you’re prepared for your code to potentially break in the future if they’re standardised. Developers use new/unstable features all the time (e.g. stage 0/1 JS proposals via Babel, nightly Rust toolchain). And I don’t believe the lack of standardisation of decorators should be a factor in deciding whether to use a library that requires these.

Re: TypeScript Features to Avoid

#27
> It may be a bit annoying to create many small files, but modules have the same fundamental functionality as namespaces without the potential downsides.

Do they?

It seems to me that namespaces are more powerful and convenient than JS modules as they enable more structure.

I have only dabbled in TS and am not sure how useful they are there. But I assume they would be similar to PHP/C#/Clojure namespaces on a conceptual level.

Re: TypeScript Features to Avoid

#28
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 whole point of compiler level annotations is to keep good programmers honest.

If some devious JavaScript developer wants to ruin your library, that's their fault.

[0]: https://codegolf.stackexchange.com/a/28818/13944

Re: TypeScript Features to Avoid

#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.

Post reply on HN