Hacker News new | past | comments | ask | show | jobs | submit login

TypeScript is, in fact, awesome. 2.0 adds still more awesomeness, and 2.1 has async/await compiled down to ES3/ES5, which I will be very happy to see.

The only thing that I don't understand is why TypeScript isn't just considered a required client (or Node) Best Practice at this point.

There are other languages that I prefer for specific domains, of course. But if you're writing code that needs to run on a web client and/or that needs to run in Node, TypeScript is the only way to go.




For me, I've simply decided to just focus on javascript. I have to use it, and while I had quite a bit of enthusiasm for Coffeescript, the move towards ES6 has made me realize that I need to just buckle in.

Maybe it's a little bit of fatigue setting in, but at this point, my next foray into a new language will be something properly compiled like Rust or Swift, not a transpiled language.

This is not to detract from Typescript or Purescript or anything else like it. There's some amazing work going on, but for now, I'd rather learn the ins and outs of javascript instead, warts and all.


It is good indeed to have a deep understanding of Javascript before using other tools.

I've never really cared for Coffeescript (because I felt like it brought very little at the cost of a very different syntax) but Typescript really improves my productivity.


I do miss meaningful whitespace. It's my favorite thing about Python. Although I recognize it's not for everyone, and it's purely a matter of aesthetics and preference.


Yeah, I have been all-in on CoffeeScript until recently, and significant whitespace is one of its best features for me. It's a DRY issue.


Give Kotlin a try. It's a JVM-language and 100% java-compatible, but it can also compile to Javascript (not sure if that backend is production-ready yet though)

https://kotlinlang.org/

It's also backed by JetBrains the IDE-maker.


I recommend you try the JavaScript backend.

I'm so sick of people spewing JetBrains' marketing points without checking the substance of it.


> I'm so sick of people spewing JetBrains' marketing points without checking the substance of it.

I tried the backend already, last time I checked it wasn't production ready, like I pointed out in my post. Maybe it is now?

OP mentioned he wanted to "foray into a new language will be something properly compiled like Rust or Swift, not a transpiled language."

Where exactly did my suggestion to try Kotlin go awry?


Kotlin is a JVM clone of swift.


They're actually quite different - a good chunk of my current project is in Kotlin, and all of my last project was in Swift.

Things Swift has that Kotlin doesn't: associated types, file-based access control (changing in Swift 3.0), pervasive use of keyword arguments, trailing closures, full pattern matching (Kotlin can only destructure component1...N sequences), reference counting.

Things Kotlin has that Swift doesn't: smart casts, declaring properties directly in the constructor, declaring constructors directly in the class statement, auto-delegation, data classes, singleton objects, implicit parameterizable 'this' (handy for builders & DSLs), garbage collection.

Things they both have: null chaining & defaulting, class extensions, somewhat clumsy first-class method syntax, concise lambda syntax, lambda anaphora ('it' in Kotlin, $0 and $1 in Swift), concise range operators, property descriptors, operator overloading.

Kotlin generally has the feel of a much more pragmatic, industrial language. It's Java without the warts, where the designers took note of the common Java patterns they wrote and provided a lot of syntactic sugar to dramatically improve brevity. Swift feels more academic; its type system is more modern and less ad-hoc, it has polished implementations of many features that academic languages have been trying to get right for years. Both are heavily influenced by their ecosystems; Swift feels like a better Objective-C, and Kotlin feels like a better Java.


Kotlin does have trailing closures: https://kotlinlang.org/docs/reference/lambdas.html#higher-or...

And some form of pattern matching via the "when" keyword: https://kotlinlang.org/docs/reference/control-flow.html#when...


It's a bit different in Swift. Kotlin lets you omit the parentheses if the closure is the only argument to the function. Swift lefts you place the lambda outside of the parentheses if the closure is the last argument to the function. That lets you construct a much larger variety of control-structure-like HOFs. Event handlers, for example, often take a functional argument plus a bunch of other data.


No, it's the same in Kotlin, from the docs:

"There is a convention that if the last parameter to a function is a function, that parameter can be specified outside of the parentheses."

So you can have normal arguments and specify the last parameter outside like.

    val col = "A"
    val row = 3
    table.update(col, row) {
       it * 5
    }
You may have confused that with SAM-conversions (?), which are for java-interop: https://kotlinlang.org/docs/reference/java-interop.html#sam-...


Cool. Learn something new every day. (I was confused because all the examples except for lock() are single-arg, and IntelliJ usually autocompletes with parentheses because there's often a non-functional overload.)


A clone of something that appeared 3 years later? (2011 vs 2014 according to wikipedia)


AFAIK the official line has always been that it's a "simpler Scala". Not to mention that it's several years older...


Scala compiles to JavaScript, to the JVM, to Android, and (soon) to native. Give it a try!


Not a huge fan of Scala[1], but it must be said that Scala.js is AMAZING for what is does. We've been using it in production since 0.4 (I think?) and we've never had any problems that could be traced back to sjs.

[1] Long story. "Trapped" programming Scala instead of Haskell by my own conservatism -- and now -- the need to support legacy systems. Still... it's way better than Java, so at least there's that. When thinking of Kotlin I always think of it as a sort of "what Java should have been", but when thinking of Scala I can't help but think "Well, it's not quite Haskell, is it?". (The poor type inference, the whole OOP thing, the lack of TCO means that any Monadic abstraction must be trampolined and that's just cruel.)


> but when thinking of Scala I can't help but think "Well, it's not quite Haskell, is it?". (The poor type inference, the whole OOP thing, the lack of TCO means that any Monadic abstraction must be trampolined and that's just cruel.

Some good news:

- Better type inference at the place were it was sorely needed landed in 2.12 (use -Ypartial-unification to enable) or use it on 2.11 with a compiler plugin.

- Even if you are not a fan of OO (I'm not), I still love that I get a great module system for free. Haskell's module system is a completely mess.

- Scala-Native already supports all kinds of TCO, including mutually recursive ones.


Oh yeah, definitely looking forward to 2.12. Don't get me wrong Scala is still good, just not great. (Hence the scare quotes around "trapped")

> - Better type inference at the place were it was sorely needed landed in 2.12 (use -Ypartial-unification to enable) or use it on 2.11 with a compiler plugin.

I was actually thinking of things like local definitions not needing type signatures. It's really easy to underestimate how much more fluent this makes the language feel. (Think of functions defined in 'where' clauses and things like that. Entirely subjective, but there's this feeling of fluency when you don't need any type signatures for non-top-level things.)

I don't think Scala is ever going to move away from requiring all functions to have an explicit type signature.

> - Even if you are not a fan of OO (I'm not), I still love that I get a great module system for free. Haskell's module system is a completely mess.

Not so much "mess", I think... more completely underpowered? It's really just a namespacing mechanism.

Hopefully we'll get Backpack at some point...

> - Scala-Native already supports all kinds of TCO, including mutually recursive ones.

Really? This is surprising to me, but perhaps they've gone with the Pascal(?) calling convention so as to make it trivially supportable?

It's still sad it can't be relied upon per language spec. :/


> It's still sad it can't be relied upon per language spec. :/

There is a @tailrec annotation which ensures that a method was optimized. It probably needs to be updated to understand Scala-Native's new abilities, but the infrastructure is there!


Yes, but IIRC it doesn't work for mutually recursive methods or dynamic(!) tail calls.


Yes, because Scala-Native only exists for a month at this point in time.


Hm? Not sure why you're bringing up Scala-Native again... @tailrec has existed since 2.8(?).

The limitations of @tailrec are obviously due to the JVM, but I was thinking (given your mention) that maybe Scala-Native had done away with the problem -- if you use the "Pascal" calling convention I believe it's mostly completely trivial to do TCO. (Just omit the "push/pop things onto/off stack" bit in the caller and use "goto".)


> Not sure why you're bringing up Scala-Native again

Weren't talking about that?

> @tailrec has existed since 2.8

Yes?

> I was thinking (given your mention) that maybe Scala-Native had done away with the problem

It uses fastcc, and yes it does. I don't understand the issue.


I'm a Scala Dev now, and I also played with Haskell and various LISPs.

I'm one of those that likes OOP and Scala's OOP is the best I've used thus far. And the great thing about Scala is that OOP is consistently used to express everything in it.

Scala gets compared with Haskel, but let's compare it with Ocaml. This isn't like Ocaml where you have the HM type system and functors and ADTs and then you have OOP as a separate thing, effectively having two type systems in the same language, while at the same time providing no means for ad-hoc polymorphism, while higher kinds are sort of a hack.

People also underestimate the importance of having the JVM as your runtime. At the very least it means you get a capable GC, which makes it feasible to use persistent data structures, and it also means you get multithreading and thus a memory model. Ocaml still doesn't have a memory model, while the GC needs improvement.

But back to Haskell. Type-classes are great as a concept, but the implementation leaves something to be desired. First of all in Haskel they are anti modular, because you can't have two conflicting definitions in the same project (not scope, but project). The standard, Haskell 98, is actually unfit for real work, with people referring in fact to GHC and its extensions. Extensions that are often experimental and unstable. And then you've got a powerful type system, but guess what, virtually no IDE tooling is available. And while its laziness is cool, in practice it can get really hard to reason about performance or about the time and space complexity.

On the poor type inference of Scala, well, it comes with subtyping. While I'm sure it can be improved, basically if you want OOP, you have to accept weaker type inference. As I said, I happen to like OOP, so I consider that to be a reasonable trade-off.

On the lack of TCO, this only really matters for performance reasons. But guess what, the JVM usually beats Haskell in performance by a significant margin, even without TCO. And no, not all monadic abstraction need trampolines. Those are quite few actually, most commonly: Free, IO and Task.

Then there's the tooling aspect. Scala has really capable IDEs (plural). And it has SBT and Scala.js. I mean, when I first started to play with Haskell I wondered if a language be that good as people say, when its build tool Cabal is such a piece of shit. You like Scala.js, yet you're not wondering why only a couple of people managed to build it and it's miles ahead of anything similar for Haskell or Ocaml or F#? Actually the only achievement similar to Scala.js would be ClojureScript.

One last note: if you want Haskell, then use Haskell. But functional programming isn't necessarily about Haskell and its idioms and Scala is its own language. In other words, you can also say that Haskell isn't Scala and people expecting Scala would be disappointed.


Thanks. I couldn't have said that any better!


I love Scala, but last time I tried to build an Android app using it (about a month ago), I just got various weird errors in IntelliJ when trying to build it. Eventually I just gave up and rewrote my app in Kotlin instead.

But yeah, it's absolutely my first choice for JVM or web work.


That sounds weird. How did you build it? Can you paste the SBT error?


It happened with both the make button and when running it (yes, I had removed the "Gradle-aware make" step and replaced it with android:packageDebug from the SBT shell plugin).

Sadly, I don't have the error message anymore, and it seemed to work when building from the command-line tool. I suppose I could have kept going like that, but it's very nice to have the proper debugging tools that an IDE provides. :/


Which version of sbt-android do you use?


1.6.1, I think, but I'm not sure. I was stupid enough to delete my project files...


>2.1 has async/await compiled down to ES3/ES5, which I will be very happy to see

The complete lack of visibility for such things is what prevented me from adopting TypeScript. I couldn't get a clear answer which platforms supported async/await (there was a huge conversation on github which heavily implied, but never outright stated, that there was an ES5 target; yet the docs said it was ES6 only). A lot of the features have unspecified targets.

I wish their documentation were better.


I agree with the spotty documentation. That said, it is nonetheless such a titanic improvement over standard JS, both in terms of safety and of readability (documentation via type signatures), that I firmly intend to not write "standard Javascript" in the future if I have any say at all in the matter.


Because there are ppl (like me) who think that strong types are highly overrated and the transpiling stuff becomes more and more obsolete with ES2015/ES7 coming. If i have to use JavaScript (and i enyoj it) then please pure without anything on top.


It's actually really, really hard to overestimate how amazing having optional specified types is. I used to use C++, then went to Lua, and more recently to JavaScript with the occasional Python. I loved the freedom of getting away from the strict C++ type system, which mostly felt like it was holding me back.

But the thing that bothered me the most about JavaScript/Python was the fact that the tooling just doesn't have a clue, most of the time, what types things are. Misremember what has a member of what, exactly, or the spelling of a member, and you've got a bug.

TypeScript eliminates that kind of stupid bug and overall speeds up development by 2-3x. Yes, some of those bugs can be found in tests. But having to go back and fix them at all, tracking down exactly what the object structure is by hand (either in a debugger or digging through docs) versus "let the editor tell you exactly what members this class/object has, and what members its children have, so I can get it right the first time"?

And what about refactoring? TypeScript knows what everything in your code is. You decide to rename a member? Done! Just because there are twenty "init" methods, if you decide this particular call should become "init2", it will rename exactly the right members throughout your project.

Finally, the fact that it just has your back when assigning types prevents another entire class of bug.

No question; (optional!) strong types are a huge win, and as I said above, should be a required practice for any nontrivial app. You get the best of both worlds: Type safety without the manacles of having to specify everything.

Transpiling won't be obsolete until TypeScript is standard in browsers (where it could help improve JIT optimizations!), and probably not even then: We're looking at ES2017 before async/await is ready, which probably won't be in most browsers until 2018 at the earliest, and there will likely be more killer features on the horizon in the future that many people will want to use.


Can typescript be integrated with other, standards-compliant preprocessors? It sounds irritating that Typescript 2.1 will "add" async/await when it's been available in Browserify and Babel for years already. I want to get into using js types, and typescript seems to have the most momentum, but I don't want to get locked into o e monolithic preprocessor which lags behind everything else by several years.


Yes, you can just target ES6/ES2015 in your emit and TypeScript will use generators to enable `async` & `await`. You can then use Babel as the next step. We have a tutorial on Gulp & TypeScript that hooks up Babel and Browserify: https://www.typescriptlang.org/docs/handbook/gulp.html


Typescript actually already supports async/await since version 1.7, but only for ES6 targets - i.e. it compiles everything down to generator-based coroutines, which is essentially the same as the 'transform-async-to-generator' plugin in Babel, I guess. If you want to support ES5/3, I guess you can always target ES6 with Typescript and then feed the result to Babel. It's a bit clunky, but it would probably work.

Where Babel shines vs. Typescript is that you get much more fine-grained control over which transformations to apply. Typescript doesn't seem to support just emitting async/await directly, which is what you would want if you target a browser which support async/await directly (Beta Chrome and Edge already support it behind a flag, and it's going to come to other browsers soon)


> The only thing that I don't understand is why TypeScript isn't just considered a required client (or Node) Best Practice at this point.

Seriously ? because it's not javascript and never will be.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: