TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

TypeScript Features to Avoid

254 pointsby gary_bernhardtover 3 years ago

44 comments

leodrieschover 3 years ago
Despite the large amount of criticism in the comments here I think that the point the article makes here is pretty valid.<p>The described features are not what TypeScript itself wants to be, and I think if it wasn&#x27;t for backwards compatibility the team would remove some of them.<p>IIRC namespaces as well as the `import = ` syntax come from a time where ESM wasn&#x27;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.<p>Enums IMO have no advantage over union types with string literals, e.g. `type Status = &#x27;fulfilled&#x27; | &#x27;pending&#x27; | &#x27;failed&#x27;`. They map way better to JSON and are generally easier to understand, while still benefiting from type safety and typo protection.<p>Well the private keyword is kind of like namespaces in that it came from a time where the feature was needed&#x2F;wanted, but the EcmaScript spec was not moving fast enough. So they made their own version of it which is now obsolete.<p>And for decorators, IIRC the decorator spec has already moved on and TypeScript&#x27;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&#x27;t recommend using decorators either, you will face breaking changes with them some time in the future.<p>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.
评论 #30008801 未加载
评论 #30015315 未加载
评论 #30008649 未加载
评论 #30015708 未加载
评论 #30015696 未加载
评论 #30013112 未加载
joshstrangeover 3 years ago
After trying enums in TS a long time back I also realized it was best to avoid them. Here is my solution to this:<p><pre><code> &#x2F;&#x2F; filename: role.ts export const Role = { CUSTOMER: &#x27;customer&#x27;, ADMIN: &#x27;admin&#x27;, SYSTEM: &#x27;system&#x27;, STAFF: &#x27;staff&#x27;, } as const; type TRole = keyof typeof Role; export type TUserRole = typeof Role[TRole]; </code></pre> Using this structure I can reference any of my roles by `Role.CUSTOMER` and the value is `customer` because it&#x27;s just a `Record&lt;string, string&gt;` at the end of the day. But I am able to type things by using my `TUserRole` so a function can required that the input be one of the values above. For me this is really clean and easy to use. Note the `type TRole` isn&#x27;t exported as it&#x27;s only an intermediary in this process, I could just as well name it `type temp` in all my files and never worry about conflicts.<p>This way I&#x27;m not spreading &quot;special&quot; strings all over my code (always a sign of code smell for me), I can changed everything at a central location, and it&#x27;s valid JS (it&#x27;s just an object).<p>EDIT: I know that `as const` seems unnecessary but I&#x27;m pretty sure it&#x27;s needed for some reason, I whittled this down to the smallest&#x2F;simplest code block I could and I just copy&#x2F;paste this pattern whenever I need enum-like functionality.
评论 #30010327 未加载
评论 #30011903 未加载
评论 #30010462 未加载
评论 #30010381 未加载
smoyerover 3 years ago
The arguments against the four language features in this article all boil down to it not being Javascript. If I wanted to write in Javascript, I&#x27;d use files with a <i>.js</i> extension. If you&#x27;ve picked Typescript, I don&#x27;t think you should worry about whether your code is also valid Javascript &quot;if you remove all the type information&quot; (who&#x27;s going to do that anyway.)<p>Unless you&#x27;re a solo developer, what&#x27;s more important it to agree on languages and conventions that apply to your team&#x27;s projects. Once that&#x27;s done, any change to the team&#x27;s work process should be a conscious, measured decision.<p>Note that I also used CoffeeScript 10ish years ago and still consider it to be a superior experience to working in plain-old Javascript.
评论 #30012244 未加载
评论 #30011886 未加载
baryphonicover 3 years ago
&gt; 1. Avoid Enums<p>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.<p>Also, TypeScript gives general intersection types, which is quite rare among its peers. (What I wouldn&#x27;t give some days for mypy to have intersection types, or bivariant functions, or conditional types, or ...)<p>The only other impetus for this post I can imagine is some weird desire to see typescript as a strictly separate layer above JavaScript that &quot;could be removed&quot; if we wanted it to be. I suppose that was the project&#x27;s original telos, but today the abstraction is leaky in a few places. I&#x27;m a world where JSX is common and radically departs from what would be considered normal JS, I don&#x27;t see a problem with TypeScript being leaky here and there. Hell, I&#x27;d prefer TS to be leakier and add opt-in runtime checking (i.e. code gen), because it would make my life easier in certain instances.
评论 #30008544 未加载
评论 #30008483 未加载
评论 #30008528 未加载
评论 #30008491 未加载
eyelidlessnessover 3 years ago
The reason enums are useful—and the private keyword until recently with JS adding private fields—are that they’re nominal types. You can have…<p><pre><code> enum HTTPMethod { POST = &#x27;post&#x27;, &#x2F;&#x2F; ... } enum FenceMaterial { POST = &#x27;post&#x27;, &#x2F;&#x2F; ... } </code></pre> … and you can be sure &#x27;post&#x27; is not ambiguous.<p>Private fields have the same benefit, which is particularly useful for treating abstract classes as nominal interfaces. But yes, if your target environments support private fields natively, it’s more idiomatic to use those than the private keyword now.<p>I <i>generally</i> avoid namespaces, but they’re also sometimes useful eg satisfying weird function signatures expecting a callback with additional properties assigned to it. This is of course uncommon in TypeScript, but fairly common in untyped JavaScript and its corresponding DefinitelyTyped declarations.
评论 #30020368 未加载
评论 #30012306 未加载
Vinnlover 3 years ago
This basically comes down to: avoid TypeScript features that clash with TypeScript&#x27;s design goals. Specifically, the one to:<p>&gt; Avoid adding expression-level syntax.<p><a href="https:&#x2F;&#x2F;github.com&#x2F;Microsoft&#x2F;TypeScript&#x2F;wiki&#x2F;TypeScript-Design-Goals" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;Microsoft&#x2F;TypeScript&#x2F;wiki&#x2F;TypeScript-Desi...</a><p>And that makes sense to me. IMHO it&#x27;s best to consider TypeScript as a tool that aims to help you write JavaScript by catching common errors; it&#x27;s more like a linter than a separate language in that regard, and is what sets it apart from something like CoffeeScript, and helps it avoid falling into the same traps.
评论 #30011351 未加载
评论 #30010419 未加载
maronatoover 3 years ago
The article&#x27;s premise is wrong imo. Typescript is a superset[1] of javascript, so typescript-only syntactic sugar is entirely to be expected.<p>[1]: <a href="https:&#x2F;&#x2F;github.com&#x2F;microsoft&#x2F;TypeScript" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;microsoft&#x2F;TypeScript</a> (repo description)
评论 #30009591 未加载
dmarchukover 3 years ago
I&#x27;ve never had any issues with enums, namespaces or private keywords (can&#x27;t speak for decorators as I haven&#x27;t used them yet). Although I do understand the reasoning for using the &#x27;#somePrivateField&#x27; rather than &#x27;private somePrivateField&#x27;.<p>But features like enums are part of the reason why we even have tools like TypeScript, because JavaScript lacks these features.
评论 #30008222 未加载
chrismorganover 3 years ago
For people that don’t see the problem and are happily using these features, here’s an explanation of the <i>second</i> problem with these sorts of features, additional to the “it’s not just JavaScript with types which is what the label said” reason which is the focus of the article.<p>The real trouble occurs when TypeScript implements something because that looks like the way things are heading, but then they don’t head that way, and JavaScript and TypeScript diverge <i>incompatibly</i>. The type stuff is generally fairly safe, and fundamentally necessary, but some of the other stuff they’ve added isn’t safe and isn’t… <i>as</i> necessary, at least. Decorators are the current prime case of this divergence problem: they added a feature because it was useful, lots of people wanted it, and that was what people expected JavaScript to get before long, and some were using already through a Babel extension but people were sad about having to choose between nifty features (Babel) and types (TypeScript); and then because they’d added something not in JavaScript, why not go a bit further? and so reflection metadata came along; and then… oh, turns out decorators are actually heading in a completely different and extremely incompatible direction in TC39 now, but people are depending on our old way and PANIC! It’s been a whole lot of bother that will continue to cause even more trouble, especially when they try to switch over to the new, if it gets stabilised—that’s going to be an extremely painful disaster for many projects, because “experimental” or not, it’s a widely-used feature of TypeScript.<p>This is not the only such case; there’s one other that caused a lot of bother comparatively recently, but I can’t think what it was (I don’t work in TypeScript much).<p>Sciter used what was loosely a fork of JavaScript when it started, and diverged, for quite decent reasons in some cases I will admit, but this divergence caused more and more trouble, until recently they gave up and switched to JavaScript, … except with a couple of incompatible deviations already and more on the table as probabilities. Sigh. I had hoped a lesson had been learned.<p>So yeah, I’m content to call these things misfeatures. TypeScript overstepped its bounds for reasons that seemed good at the time, and may even have been important for social reasons at the time, but you’re better to avoid these features.
评论 #30014303 未加载
评论 #30008735 未加载
yCombLinksover 3 years ago
He is completely incorrect about the purpose of enums. It isn&#x27;t to simplify changing all locations of an occurrence. It is for defining domain concepts. It is to communicate to other code users, here is every allowed permutation of this type.
评论 #30011327 未加载
评论 #30011722 未加载
_zootedover 3 years ago
Article makes no real good arguments about not using the private keyword. It&#x27;s more descriptive and carries knowledge from other languages compared to putting a hashtag in front of a variable name.
评论 #30011072 未加载
01acheruover 3 years ago
&gt; it has to generate new JavaScript code that doesn&#x27;t exist in the original TypeScript code<p>That’s nonsense, the code is there otherwise what are we talking about?<p>You just need to understand how some TS features map to JS, that’s all.
评论 #30008341 未加载
crabmusketover 3 years ago
&gt; We recommend the new #somePrivateField syntax for a straightforward reason: these two features are roughly equivalent.<p>The author of the article surely knows the significant difference between JS private fields and TS private fields: TS private fields can be easily circumvented, whereas JS private fields cannot. See TS playground link[1]<p>I think this is a significant enough point that people should <i>not</i> be taught that TS&#x27;s private is just a different way of doing the same thing. I&#x27;ve always said that TS is basically a fancy linter, and sometimes that&#x27;s exactly what you want.<p>TS&#x27;s private keyword communicates programmer intent, but lets you do what you like when you really have to. Just like the rest of TS.<p>[1]: <a href="https:&#x2F;&#x2F;www.typescriptlang.org&#x2F;play?#code&#x2F;MYGwhgzhAECC0G8BQ1XQA4CcCWA3MALgKbRgBc0EBOAdgOYDcKawA9jVZgK7AGuYAKAJSJmaNAQAW2CADow0ALzQARGBVNxAXyQ6kIIgWisARgCsl0GkQDucYUwNGCAT3REAopkz8KnbPSWpmbyjobQ2ADSNKw2AOqShACSALYAIqwBdH7UWUHmANpqKgC6DEA" rel="nofollow">https:&#x2F;&#x2F;www.typescriptlang.org&#x2F;play?#code&#x2F;MYGwhgzhAECC0G8BQ1...</a>
评论 #30018414 未加载
conaclosover 3 years ago
Replacing TS enum with JS objects is really tedious:<p><pre><code> type HttpMethod = keyof typeof HttpMethod const HttpMethod = { GET: &quot;GET&quot;, POST: &quot;POST&quot;, } as const </code></pre> It is even worse with int enum:<p><pre><code> type HttpMethod = Extract&lt;keyof typeof HttpMethod, number&gt; const HttpMethod = { GET: 0, POST: 1, 0: &quot;GET&quot;, 1: &quot;POST&quot;, } as const </code></pre> My personal &quot;avoid&quot;-rules are:<p>- Avoid enum with negative integers because it generates code that cannot be optimized by the JS engine<p>- Prefer ESM modules to namespaces, because the first can be tree-shaked.
评论 #30010095 未加载
comp_throw7over 3 years ago
I think enums should be avoided for a few reasons not described in the article (some of them are mentioned in other comments here).<p>1) Enums have a unique (and, imo, mostly undesirable) model for interacting with the rest of the type system, which isn&#x27;t what you&#x27;d naively expect. If you try to treat an enum like an object-literal (`as const`) when it comes to type-level manipulation you&#x27;re going to have a bad time.<p>2) Implicit numeric enums (i.e. the ones most people use by default because they require the least amount of typing) make adding new values a _backwards-breaking change_ if you insert them before existing values, and you send them over the wire. Let me repeat that: adding new values to an existing enum is a _breaking change_.<p>3) Giving a field or parameter an enum type will not actually cause the Typescript compiler to complain if you put in a value that&#x27;s not part of the enum! Example:<p>``` enum Fruit { APPLE, BANANA }<p>interface FruitSalad { base: Fruit }<p>const salad: FruitSalad = { base: 5 }; ```<p>Assigning `5` to `base` (which, you might expect, would only accept `Fruit.APPLE` and `Fruit.BANANA` - and perhaps even `0` and `1` as valid values) is in fact something that the compiler will let through without complaint.<p>4) Debugging is a headache, since reverse-mapping them gives you... a number.<p>You might say that most of these problems are solved by using string enums - sure, but then why not use an object literal instead? To save yourself from needing to write a single additional type definition? IMO, that is not worth the issues you run into with respect to the first problem.
antiheroover 3 years ago
I disagree with the point about enums, they can be used to alias otherwise inconsistent long strings with more readable, consistent, succinct ones. For instance, product SKUs. I&#x27;ve had absolutely no problems with them with either past or current tooling (e.g. esbuild).<p>They can also be used in the more traditional form to represent some arbitrary values.<p>They shouldn&#x27;t be overused, though.
seniorsassycatover 3 years ago
Lots of comments seen to have missed that the article isn&#x27;t recommending against private fields, only the private keyword.<p>Typescript and JavaScript have a newer brand # to make fields private. The native feature will have runtime benefits while the private keyword creates fields that&#x27;s are public at runtime.<p>I still use the private keyword because constructor shorthand doesn&#x27;t support brands.<p><pre><code> constructor (private field) constructor (#field) &#x2F;&#x2F; error</code></pre>
评论 #30012201 未加载
Tabular-Icebergover 3 years ago
My problem with enums isn’t so much that it breaks type-level extension, it’s that it breaks structural typing.<p>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.
评论 #30008390 未加载
matt7340over 3 years ago
I like these recommendations, especially around decorators, maybe I’ll start following them<p><i>reviews Angular app</i><p>oh
评论 #30009464 未加载
samwillisover 3 years ago
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.<p>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.<p>I suppose in some ways it&#x27;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.<p>It comes down to personal&#x2F;team preference, what works for you.<p>Personally with TypeScript I&#x27;m inclined to code in a &quot;closer to JavaScript&quot; way (but taking full advantage of types obviously), but would happily work in whatever style was prevailing in the project.
breatheoftenover 3 years ago
Is anyone still using the class keyword in javascript or typescript? private field syntax doesn&#x27;t matter in the first place if you don&#x27;t use class {} anywhere ...<p>I feel like most of the typescript code i&#x27;ve been in recently looked like it needed 0 more class declarations.
评论 #30010948 未加载
评论 #30015745 未加载
评论 #30021601 未加载
评论 #30009520 未加载
评论 #30015889 未加载
jacobrover 3 years ago
The TypeScript documentation even states &quot;In modern TypeScript, you may not need an enum when an object with as const could suffice ... The biggest argument in favour of this format over TypeScript’s enum is that it keeps your codebase aligned with the state of JavaScript, and when&#x2F;if enums are added to JavaScript then you can move to the additional syntax&quot; <a href="https:&#x2F;&#x2F;www.typescriptlang.org&#x2F;docs&#x2F;handbook&#x2F;enums.html#objects-vs-enums" rel="nofollow">https:&#x2F;&#x2F;www.typescriptlang.org&#x2F;docs&#x2F;handbook&#x2F;enums.html#obje...</a>
captainmuonover 3 years ago
I think the attitude that they show in #1 - that TypeScript is only supposed to add typing to JavaScript and everything that goes beyond is bad - is wrong.<p>In fact, the only major problem I have with TypeScript is the lack of operator overloading [1]. This feature has been denied with the exact same justification. They will not add any feature that emits additional logic, so they cannot add operator overloading unless JS adds it. Also they will not add anything that needs runtime type lookup.<p>I think very simple, stupid syntactic sugar would be sufficient to solve 90% of use cases. For example, and please don&#x27;t take this apart, I&#x27;m just making it up on the spot: transforming `a + b` to `a._op_add(b)` if a is not provably `any` or a primitive type.<p>Without operator overloading, for example vector math looks really ugly. I hope somebody will make at least a babel plugin or something to allow that.<p>[1]: <a href="https:&#x2F;&#x2F;github.com&#x2F;microsoft&#x2F;TypeScript&#x2F;issues&#x2F;6936" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;microsoft&#x2F;TypeScript&#x2F;issues&#x2F;6936</a>
dgb23over 3 years ago
&gt; It may be a bit annoying to create many small files, but modules have the same fundamental functionality as namespaces without the potential downsides.<p>Do they?<p>It seems to me that namespaces are more powerful and convenient than JS modules as they enable more structure.<p>I have only dabbled in TS and am not sure how useful they are there. But I assume they would be similar to PHP&#x2F;C#&#x2F;Clojure namespaces on a conceptual level.
fifticonover 3 years ago
I cannot agree regarding enums. I want enums exactly as they are. In particular, I insist on decoupling their names and their values. I want to rename&#x2F;update their names, without affecting their representing value. I want them to work with both integers and strings (as they do). Their raw values may appear in external data, for reasons that are none of your business, and thus must be preserved, maintained and under control. The enum as it exists was created by people who know what they are talking about when they talk about enums. People are free to go in their corner and play with their union types and crayons, but they should not confuse them with enums. There is nothing wrong with union types, apart from them being union types but not enums. The language with the best enums is java - enums in java are so great, that I often regret the hoops I have to jump through with enums in C# (you might well say, enums in java are overengineered).
ortaover 3 years ago
Yeah, for sure, I agree with all of this. I think the best way to write TypeScript is to really treat it like the tagline &quot;JavaScript With Syntax For Types&quot; - some of the extras TypeScript provided from before TC39 were active have much less relevance now.
sgtover 3 years ago
We evaluated TS for a recent project but ended up with JS (and VueJS 3). I have a feeling it would have taken much longer to develop using TS, but lacking experience in TypeScript it&#x27;s hard to say. I find JS pretty neat for exploratory programming.
评论 #30011027 未加载
G3rn0tiover 3 years ago
I think this whole discussion of whether union types are better than enums sheds light on the issues I have with type script in general: It’s basically a JS extension (like coffee script btw — remember that?) that is supposed to make your life easier as a developer but instead introduces a huge amount of unnecessary complexity giving you even more head aches.<p>I’ve yet to see typical front end code that really benefits from strong typing or even just the use of enums. I tend to accept language limitations and focus on designing my programs around those instead of wasting my energy on fighting on niche language extensions…
Tade0over 3 years ago
I thought this is going to be about dependent types or the `infer` keyword(or any other badly documented feature like the latter).<p>There are features of the type system you should definitely avoid unless you&#x27;re writing a library. Enums aren&#x27;t it.
samrockscover 3 years ago
TypeScript has a lot of features that just generate cognitive overhead that could have been better spent just learning a different language.<p>I like TypeScript a LOT, but to be honest I only use about 10% of it. Anything more than that and it gets too confusing for the next developer in line to work on the code in my experience.
Tyriarover 3 years ago
Const enums specifically are great, since they disappear on compile you can use them to internally document strings&#x2F;numbers with verbose names&#x2F;comments without the cost of a const variable that would appear after compilation.<p>As for the fact that types cannot simply be stripped out, I&#x27;ve found building using plain tsc and have the bundler target tsc&#x27;s output directory. This separation is needed since most tools don&#x27;t support TypeScript project references anyway which I find extremely useful for organizing internal modules.
donatjover 3 years ago
The reasoning behind most of this, that the output JS is not a strict subset of the input is silly and imho represent a misunderstanding of what Typescript is going for. It’s a full fledged language that compiles to readable JS, not just <i>annotated JavaScript</i>.<p>There are many features in Typescript where it simply isn’t just outputting a subset of the input, and many of them are the best parts of Typescript.<p>If you just want JavaScript with types, there are other languages that do that, but Typescript offers so much more.
评论 #30009399 未加载
评论 #30009626 未加载
davedxover 3 years ago
The arguments not to use them are implementation details of the tooling.<p>Well designed Abstractions are good, not bad…
remorsesover 3 years ago
I would also suggest to avoid too complex genrics, these tend to make te code unreadable and make the compilation super slow.<p>Usually generic code tries to make everything type safe but having some portions of your code be dynamic is completely fine imo.
mikojanover 3 years ago
As long as you are not using &quot;const enums&quot; JavaScript&#x2F;TypeScript interop is not a real problem at all.<p>The private keyword is obviously preferable to &quot;#&quot; in environments in which you are targeting older ES versions.
评论 #30008495 未加载
EMM_386over 3 years ago
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.<p>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&#x27;t need to be made visible to the view template or outside of the class. I honestly don&#x27;t care <i>what</i> this transpiles down to, the point for us at least is not to make things &quot;truly private&quot; (good luck with that in JavaScript). It&#x27;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.<p>I also enforce that we actually make things as public although that isn&#x27;t needed, and I enforce returning void.<p>So instead of:<p>someMethod() {}<p>I have us use:<p>public someMethod(): void {}<p>Just to state what you intend.<p>I realize &quot;I don&#x27;t care what this transpiles down to&quot; might really irk some people, but I really don&#x27;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&#x27;t care. Just give me a clean code base that enforces we can&#x27;t reference private fields and methods from our templates.<p>For enums, I recently wrote a method that does exactly what this article says not to do, use it for GET, POST, and PUT.<p>What would be a <i>cleaner</i> way to write this? If it has to be refactored into something much &quot;uglier&quot; I don&#x27;t think I&#x27;d prefer it.<p><pre><code> this.downloadService.fileWithProgress(url, RequestType.post, ActionType.download, body) </code></pre> 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.
评论 #30008396 未加载
评论 #30010473 未加载
AbuAssarover 3 years ago
You can use const enum and the ts compiler will just replace any enum reference with its value inplace.
auggieroseover 3 years ago
Enums are fine, just don&#x27;t forget to use Object.freeze(enumName) afterwards!!<p>Apart from that, because Typescript has powerful union types, not using enum is perfectly fine as well, for example instead of:<p><pre><code> enum Relation { Less = -1, Equal, Greater } Object.freeze(Relation); </code></pre> you could do instead:<p><pre><code> const Less = -1; type Less = -1; const Equal = 0; type Equal = 0; const Greater = 1; type Greater = 1; type Relation = Less | Equal | Greater; </code></pre> Apparently you need the additional &quot;type Less&quot; etc. declarations, I would have thought it should work without.<p>As for private and #, the biggest disadvantage of # is that it is so slow currently. But that will change hopefully soon when # is not compiled as WeakMaps by TypeScript. I would hope they compile private to # later on, backwards compatibility be damned :-D
评论 #30016288 未加载
ameliaquiningover 3 years ago
This whole thing feels basically grounded in purity over practicality. In general it&#x27;s a good idea to write idiomatic TypeScript. Even when I agree with the given recommendations, the given reasons don&#x27;t seem like the strongest ones.<p>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&#x27;re generally convenient and fill a useful niche, especially numeric enums with implicitly assigned values. (I&#x27;m also curious what the article&#x27;s authors think of const enums.)<p>Namespaces have been soft-deprecated, modules are pretty much just better, and so I quite agree that you shouldn&#x27;t use them, though I&#x27;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.)<p>Decorators, especially with metadata, facilitate lots of useful things that otherwise just aren&#x27;t possible in TypeScript. It&#x27;s also the case (though the authors seem unaware of this) that they will <i>never</i> 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&#x27;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 <i>incompatible form</i> and then you have an interesting migration ahead of you. TC39 won&#x27;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.<p># vs. private is mostly a matter of style&#x2F;taste, with two exceptions. First, if you have any code on your page that you don&#x27;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&#x27;t support #, then don&#x27;t use it; the compiler can downlevel it, but only at significant code-size and performance cost that you don&#x27;t want to pay (and debugging it in the browser will also be annoying).<p>Do the authors also disfavor parameter properties? Those also require emit beyond just stripping types, but are super-convenient and useful and don&#x27;t really conceptually complicate things.<p>Incidentally, the feature at the top of my own list of &quot;TypeScript features to avoid&quot; (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&#x27; knowledge of fiddly type-system details. I&#x27;m not saying it&#x27;s never worth it (and in particular the built-in utility types are usually fine even though they&#x27;re conditional under the hood), but whenever possible I try to reach for something else.
评论 #30008650 未加载
评论 #30015398 未加载
评论 #30012876 未加载
armchairhackerover 3 years ago
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.<p>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 decorators? JS already gets new features which break backward-compatibility, mine as well add features which fix compatibility with TypeScript.
评论 #30008046 未加载
评论 #30008003 未加载
评论 #30008022 未加载
015aover 3 years ago
The only point I take slight issue with is Avoiding Namespaces.<p>I can&#x27;t speak for frontend code, but on the backend:<p>It feels at least somewhat obviously true that unique names are good. Even if you aren&#x27;t operating in a language which has global imports (which is most nowadays), unique-as-possible names can help disambiguate-at-a-glance something like:<p><pre><code> const user: User = await getGoogleSsoUser(); &#x2F;&#x2F; 100 lines later... console.log(user.microsoftId); &#x2F;&#x2F; wait why isn&#x27;t that field available? &#x2F;&#x2F; ok i&#x27;ll fix this const googleUser = await getGoogleSsoUser(); &#x2F;&#x2F; obviously that makes sense; but what about the type? export function getGoogleSsoUser(): Promise&lt;User&gt; {} &#x2F;&#x2F; wait... should that return a Google API user object? or our own user model? &#x2F;&#x2F; let me scroll 200 lines up, ok its defined there, open that file... &#x2F;&#x2F; or just: export function getGoogleSsoUser(): Promise&lt;GoogleUser&gt; {} </code></pre> Contrived example of course, but it&#x27;s a broader pattern I see every day; there&#x27;s a lot of overloaded terminology in programming.<p>But this gets hairy really quickly.<p><pre><code> &#x2F;&#x2F; google will provide these types... but lets assume you&#x27;re writing your own export type GoogleUserV1 = ...; export type GoogleAPIV1GetUserResponse = { user: GoogleUserV1, } export type GoogleAPIV1ListUsersResponse = { users: GoogleUserV1[], count: number, } &#x2F;&#x2F; ok lets import them import { GoogleUserV1, GoogleAPIV1GetUserResponse, GoogleAPIV1ListUsersResponse } from &quot;my&#x2F;service&#x2F;google&quot;; </code></pre> First, the type names get really long, which makes them hard to read at a glance. Second; this cost is replicated anytime someone wants to import something. Third, they oftentimes become a seemingly randomly ordered set of words written like a sentence; why is it not &quot;GoogleV1APIListUsersResponse&quot; or &quot;GoogleAPIListUsersV1Response&quot;?<p>We can solve the second problem by doing an old-style wildcard import:<p><pre><code> import * as google from &quot;my&#x2F;service&#x2F;google&quot;; const user: google.GoogleUserV1 = await getGoogleSsoUser(); </code></pre> But this almost always ends up stuttering, because the producer package still wants to guarantee unique-as-possible exported names, as asserted above. So we made problem 1 worse, and did nothing for problem 3.<p>With namespaces:<p><pre><code> export namespace Google { export namespace User { export type V1 { ... } export type GetResponse { ... } export type ListResponse { ... } } } &#x2F;&#x2F; now to import it import { Google } from &quot;my&#x2F;service&#x2F;google&quot;; const user: Google.User.V1 = await getGoogleSsoUser(); </code></pre> The symbol, as a whole, isn&#x27;t shorter. But, it&#x27;s easier to read (and write!). It also helps disambiguate where in the symbol each component of the type&#x27;s name should reside, when the producer wants to for example add a new type or function.<p>The argument against presented by the article boils down to: it creates unnecessary fluff in the emitted javascript. That&#x27;s a reasonable argument; it does. In practice, it&#x27;s more nuanced. First: I&#x27;ve never seen it cause an issue. So, premature optimization, YMMV, etc. Second: the fluff is erased for types anyway; so it only becomes an issue for functional code defined like this (all of my examples were in types, but its easy to imagine a Google.User.List function). Third, though not a direct counterargument to the article: it&#x27;s literally how Google organizes the types we&#x27;ve been talking about [1] (though, how they organize the functional code, I&#x27;m not sure).<p>[1] <a href="https:&#x2F;&#x2F;github.com&#x2F;DefinitelyTyped&#x2F;DefinitelyTyped&#x2F;blob&#x2F;master&#x2F;types&#x2F;gapi.people&#x2F;index.d.ts" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;DefinitelyTyped&#x2F;DefinitelyTyped&#x2F;blob&#x2F;mast...</a>
_under_scores_over 3 years ago
Personally I don&#x27;t get the argument against enums. From what I can tell it&#x27;s purely to do with the symantics of what Typescript <i>is</i>, rather than any inherently bad property of enums.
shadowgovtover 3 years ago
The author misses I think an important point regarding enums: using a union type instead means you can&#x27;t iterate the list of valid values without restating them in the value domain in a non-DRY fashion. The reason enum generates code is that it is both a type construct and a value construct... That ends up being useful in myriad contexts.
concerned_userover 3 years ago
What is there left to use in the end? Type annotations?<p>Maybe recommend not to use Typescript altogether then. Their only reasoning for this seems to be that the features &quot;be more likely to break when using build tools other than the official TypeScript compiler&quot;.
评论 #30008620 未加载
评论 #30008707 未加载
评论 #30009510 未加载