Why We Chose Typescript
redditblog.com
redditblog.com
Babylon merged TypeScript support yesterday [1]. This means that in the future it should be easier to setup Babel with TypeScript.
I agree with the decision to go with TypeScript. It has drastically better community support. Most third-party components won't have flow annotations. Flow would've been a lot more successful from the start if it had started out with DefinitelyTyped support. Heck, even now I'm still wondering why they don't do that.
[0] https://codemix.github.io/flow-runtime/#/
[1] https://github.com/babel/babylon/pull/523#issuecomment-31172...
I never did understand why Facebook and Microsoft ended up competing on this front.
They ended up competing, but they did not start competing. The projects were started in isolation from each other. The fact that they are written in different languages (Flow: OCaml, TS: TS) makes it hard to merge efforts.
flow-typed does exist, so that's something. https://github.com/flowtype/flow-typed.
I would love to have type checking, but I'm weary of solutions that aren't really JS, and could fall out of favor or lack good support in the future. I'm pretty sure I'm not the only one.
But Flow type annotations don't really need an incompatible syntax AFAIK; they could just use comments. This way, we wouldn't need to worry about the future of Flow. If the projects dies off or becomes redundant, we're just left with some useful comments - no need to rewrite or transpile our code to native JS.
PS I found an existing project which does this [1], but it requires an additional step and it isn't officially supported. It looks incredibly easy to make Flow work directly with pure JS with comments...
[1] https://www.typescriptlang.org/docs/handbook/jsx.html [2] https://github.com/s-panferov/awesome-typescript-loader
In the end i decided to stick to 'old-fashioned' SCSS with an npm script; the downsides of adding Babel to my stack weren't worth the upsides of css modules. Difficult decision to make though.
I guess what I'm saying is that while there is a use case, so far it's been worth it to just stick to TS without Babel, much as I wish it'd be different.
I like what I see and look forward to experimenting with it once I have more free-time (currently in grad-school taking summer courses). Kotlin as a language is really compelling, so I've tried to at least stay informed about it.
Sounds like they learned from their mistake of using Python on the server-side. Dynamically typed languages for large code bases are terrible.
I could not disagree with this sentiment more. As always, reality is more nuanced than this.
There seems to be a common theme of startups succeeding with dynamically typed languages, and adding static typing later. However calling the original decision a "mistake" is neither fair nor accurate.
After all, you don't buy a big mansion out of college because you are going to have a family one day. What is right for you today might not be right for you today.
Companies change as they grow, and switching from move-fast-and-break-things to slow and steady mode is just one of those things alongside all others.
Dynamic languages were great at bringing these companies where they are now: it allowed them to be agile and fast to market with a small team.
Are they going to benefit from switching? Yes, absolutely. But was the original decision a mistake just because the priorities and cost/benefit curves have changed now? I really doubt it.
Python and JavaScript are probably the most common "first languages" taught in school. The dynamic typing and lack of complex IDE, compilation, and build system make then easier to learn. Most founders only have a few years of programming experience. Most startups can't afford to hire anyone experienced. Given these constraints, using these languages makes sense.
Dynamic language aren't any faster in practice. You can write quick and dirty spaghetti code in anything. It's only the naive that consider building large, or potentially large, projects in languages without static typing and strong IDE support.
In time I've realized that dynamic typing doesn't give any real advantages. It allows you to reuse variables, something that should never be done. It allows you to put different objects in the same array without having anything in common, which also seems like a bad idea. What else do you get? The language still has types they're just not visible when your writing code. I would much rather have compile-time types so I can use auto complete
I love Ruby because of its delightful standard library, its thoughtful syntax which makes manual refactorings easy, not because or in spite of its dynamic types.
I detest Java because of its verbose syntax, its love affair with XML, and because it isn't a good unix citizen. Not because of or in spite of its static type system.
I detest Javascript because of its non-existent standard library, its many, many design errors (slowly being fixed, I know). Not because of its particular type system.
All other things being equal, I would prefer my language of choice to have statically checked, expressive type system. Unfortunately, all other things have not been close to equal historically. Things are improving, and maybe these days it's possible to have your cake and eat it too.
Types are useful when you grow, but thinking that you can't do anything big and robust without it is ignoring all the people that actually do so.
Another thing is that the simplicity and power of Python leads to having a lot of libs that are actually clean and solid for a lot of stuff. If I need to create anything under 100000 vis/day, I'm 3 times faster than a Go or Java dev on the backend. Literally 3 times.
I also produce better results. With things like Django rest framework, I can get the same REST API, but all the edge cases will be way better handled, small error messages, multi type of auth, etc.
Those things exist because it's fast to code in Python. And yes, dynamic typing help with that a lot.
So yes, it's true I don't have as much code completion and I have to remember a bit more about the code, but it's an exchange I'm making.
When I want to scale up robustness, I use type hints with mypy and get a strong code completion on PyCharm.
Java libraries, particularly those maintained by Google and other tech giants are some of the most solid code ever written. I doubt Python or any other language comes close to the quality of popular Java libraries.
I still don't see how dynamic typing helps with speed? Any Decent IDE will fill in the types for you so you don't even need to key then mostly
People always say this, and I've never understood it. Can somebody provide an example of a test that you "have" to write in a dynamically typed language that you wouldn't with static typing? If you're referencing nonexistent properties, then any test that hits that line will fail, and such a test should exist regardless of whether you're using static types.
People forget how old reddit is. Most good options in this space for statically compiled languages did not exist back then, so there wasn't really a decision to make. It even predates rails.
However, large part is that for frontend, static languages are just getting there. You need not just language, but also libraries, tutorials, tooling, IDE and so on and so forth.
Typescript nor flow does not absolve you from the need to learn javascript and web in general. If you are working on your first bigger project and still learning good techniques, architecture and concepts, css, having to also learn typescript or flow syntax on top of it off-puts people.
TypeScript was the first time I ever used a static language without feeling like it was getting in the way or I was losing the power of a dynamic language. So no, they didn't learn their mistake from using Python, they were just coaxed into using an incredible language since, barring masochism, you must compile from something into JavaScript nowadays, and TypeScript is an absolute pleasure.
- Type inference for the laziest. Hands down better than Scala, Swift, or Rust. The only language I've ever used that can infer recursive functions:
function factorial(n: number) {
if (n == 0 || n == 1) return 1;
else n * factorial(n - 1)
}
- You can define mix-typed maps without a sweat:
const defaults = { debug: false, title: 'Banana', width: 100 }- And as a bonus you can suck the type out for later use:
type Settings = typeof defaults
- You can mix types without the compiler demanding umpteen incantations.- Gloriously simple union types.
- Regex types are coming! (e.g. all strings that look like a URL)
- You can type the API of some hidden dynamically-typed insanity if needed.
- You get a REPL for free, and it's pretty easy to debug production code if you haven't mangled all your names.
- Haven't figured how to type something? Want to prototype something quickly? No worries! Your code will still compile.
That's called a struct (or class) elsewhere.
Elsewhere one would have to define a struct/class and them create an instance.
This becomes immensely helpful for the incredibly lazy with one off object definitions and wrapper types. If you introduce a class definition alongside an instance, you're now forced to manage two peices of code. The class definition and instance definition. In this case they're coupled which aides maintenance in my experience.
What are interesting use cases for more dynamic (i.e. non-fixed set of keys / types)?
I mean, if you need something super-abstract and flexible, you are unlikely to need a built-in convenient syntax to hardcode such values.
For those new to this, good search terms are "row polymorphism", "extensible records", and "polymorphic variants".
Any of the mainstream functional languages (which are most likely to have type inference) can infer the types of all functions, unless you use funky language extensions that make type inference undecidable. Rust has a Hindley-Milner system, so it should be able to "infer recursive functions" too (but I can't say for sure since I don't use it).
Also, mainstream functional languages aren't truly mainstream: I'd struggle to find devs who could help me in consulting gigs.
let rec factorial n =
if n = 0 || n = 1 then 1
else n * factorial (n - 1)
F#You don't need to have used other languages to see there's no problem -- just Google -- haskell recursive factorial type inference
Dynamically typed languages for
large code bases are terrible
The success of Wikipedia, Wordpress, Facebook, Youtube, GitHub etc etc etc and last but not least Reddit seem to prove otherwise.Prove how? They could have succeeded in spite of dynamic typing, not because of it. Facebook defined a new programming language to add static typing to HHVM. The process of plugging into WordPress is infamous in its disorganization.
There’s a lack of good statically-typed languages, so it’s natural for many popular things to be built in dynamically-typed ones, but that doesn’t make the dynamic typing approach better.
was the original argument. Success/failure of entire companies has somehow been brought into it.
But you're right. Moreover I noticed obsession with a particular language is often a hallmark of a junior engineer or a recent grad. This this idea of "If you don't use Go/Node.js/etc you'll totally fail".
Prove how?
By means of natural selection. They could have succeeded in spite of
dynamic typing, not because of it.
You think the otherwise smart and successfull founders of these projects all made the wrong choice when it came to selecting the right tool for the job? Facebook defined a new programming language
No, they wrote a faster runtime. to add static typing to HHVM
No, they added type annotations. There’s a lack of good statically-typed languages
No, in the past statically typed languages were the norm. C, C++, Java...It's just that dynamic languages outcompeted them.
All "trending" languages are statically typed (Rust, Go, Swift, Kotlin, ...) and all the popular JavaScrip-improved-languages are statically typed as well. Even further, many dynamically typed languages have pushed in recent years to add type annotations or even static typing (e.g. mypy).
Dynamic typing is the brainchild of the 90s for rapid initial development. Sustainability has been a big issue from the outset.
Highly dynamic languages like Python or PHP or Perl are easy to start with, so they're great for prototypes. Then either a serious rewrite follows, using a statically checked language, or scaffolding is erected to continue to make do with the dynamic code. Microservices help!
Not at all! I think dynamic typing hurts code, but there are:
- not always alternatives
- many other slightly suboptimal choices that it’s quite possible to succeed in spite of
> No, they wrote a faster runtime.
I’m referring to Hack, which is in fact another language with static typing. (Type annotations are static typing with compromises, and you can see what’s being gone for.)
> No, in the past statically typed languages were the norm. C, C++, Java...
Those are not remotely good. Some examples closer to being good are Rust, a step in the right direction that’s still unfolding, and Haskell, a wonderful language hampered by a slow compiler and a lack of decent packages. (And probably several less popular languages, but popularity is an important factor…)
Which includes a statically-typed version of PHP, namely Hack, that they use for their code.
> No, they added type annotations.
Hack's type checking is much more sophisticated than mere “annotations”. That label might be better suited to PHP's type system.
Nobody is perfect. Mark Zuckerberg has had his fair share of controversies for example.
>No, in the past statically typed languages were the norm. C, C++, Java...
Not good examples for your argument. These are largely considered poorly statically typed. Compare to ML, Haskell, Ada, Rust, Swift for reference.
Yes, they could have. Evidence for your hypothesis would be the existence of similarly successful companies that used compiled statically-typed languages from the beginning.
Are there any recent ones?
Then maybe the burden of proof is on you?
If you started your career recently, it's easy to be caught up into this "static typing" as some kind of the only way.
I’m saying that the parent doesn’t prove its point, and I’m not attempting to prove its parent’s point.
> If you started your career recently, it's easy to be caught up into this "static typing" as some kind of the only way.
I didn’t, and the bulk of what I’ve built has been in languages with dynamic typing. See https://news.ycombinator.com/item?id=14675577. Dismissing stuff as “recent starts” is pretty cheap, anyway.
Also, all of the examples you cite a rather the "in spite of" kind. Wikipedia? Struggles to maintain the code base, lest to speak of significant new development. Wordpress? Afterwit of web security. Facebook? Facebook literally developed a new PHP implementation (edit: actually, two) and then turned that into a separate language (which is statically typed) because that's easier than to clean up their PHP code base. YouTube? Maybe some help pages are still on Python. The application most likely isn't at all. GitHub? Goes down every few days with 500s after buggy code was deployed.
Conversely, you're also able to write equivalent functionality with less code and with idioms you can't use in statically typed languages. It's an engineering trade off, the static typed handcuffs prevent you from making a certain kind of mistake but they also prevent you from writing certain kinds of code that are extremely powerful; many prefer the power over the handcuffs. Type bugs just aren't that painful.
> Type bugs just aren't that painful.
You haven't learned the true power of a decent type system then.
The amount of code one writes says more about the language than whether or not it's statically typed.
To me, adding "bigint" or "bool" to the occasional variable and function declaration isn't "more code", it's an extremely terse way of avoiding different code (e.g. type assertions).
Dynamic languages excel at fast initial development and "gimmicky" code (wildfire monkey patching, introspection, dynamic code generation etc.), and to get there you pay dearly. Practically all other properties suffer; stability, maintainability, performance, memory usage, ease of deployment, distribution and so on and so forth.
That doesn't mean that dynamic languages have no place, or applications developed using them are somehow generally inferior to those written in statically typed languages; choice of language is only one mosaic stone of many. But it is also a foundation stone, and dictates many constraints, both technical, and social.
As type systems vary, almost every statically-typed language allows some errors of the class statically-typed languages, in general, can prevent, so this is not really true.
What is true is that on the continuum from no static validation to something like Idris or Agda, you accept more statically-avoidable type errors the closer you are to the former rather than the latter.
The quality of your code base largely affects the ability to roll out new features with limited regressions.
Anyway, to each their own. I want "Unobtrusive Typing" to be a thing.
Look at the mess of wordpress code. It's an abomaly and security history proves how it was never a technical success.
- Wikipedia is mostly PHP https://github.com/wikimedia/mediawiki
- Wordpress is PHP https://github.com/WordPress/WordPress
- Facebook started in PHP https://www.quora.com/What-programming-languages-are-used-at...
- YouTube started in Python https://www.quora.com/Is-YouTube-still-written-in-Python
- GitHub is Ruby https://github.com/showcases/projects-that-power-github
- Reddit is mostly Python https://www.reddit.com/wiki/faq#wiki_what_is_reddit_written_...
(https://github.com/python/mypy/commits/master because I know the pain of linkless comments)
My team has been working with Clojure for the past 6 years, and we've built and maintain a number of large applications. Dynamic typing is absolutely not a problem for us.
I find that immutability plays a far bigger role when it comes to maintaining large applications. When you work with immutable data, it becomes possible to safely reason about parts of the application in isolation. This is a key factor in making large apps maintainable.
IMO it is better to start from monolith and then extract services.
You have a common set of data structures that all functions operate on. To create a piece of domain logic, I simply need to create a namespace, and put the related functions there.
This style of code is highly composable. Since majority of functions are doing generic transformations, the domain specific logic is expressed by chaining these functions in a particular way to get a desired transformation. When I need a different kind of transformation, then I just chain the functions in a different order. My experience is that the business logic naturally bubbles up to a thin layer at the top.
Had they started building it in C++ or Haskell they might still be building it with 0 customers onboard while some other company which used Python would be dominating the market.
Perhaps this is what you believe based on your experience or opinions on internet.
However large code bases, complex systems, have been used successfully, for example for:
- Driving the Deep Space 1 (DS1) NASA spacecraft for 3 days without manual input.
- Search for airline ticket reservations encompassing almost all the airports in the world and most airline companies, not to mention all the diverse routes available. Really complex stuff. (ITA software, currently in use across the globe)
These big, complex applications were written in a dynamically typed language.
Once their core feature-set is established and they've developed the product they want they can go back and optimize accordingly and rewrite parts of their code-base to use the most appropriate language, e.g. rewriting hot spots in C/C++/Rust/Go, highly concurrent features in Erlang/Go, etc. If code-maintenance becomes problematic they can explore annotating their code-base with Types, adopt linters or even rewrite into a statically-typed language. None of this is a mistake, languages/technologies are a tool to achieve your business objectives, if adopting a dynamic language lets you get an MVP quicker and add/change features based on Customer feedback quicker, then that's likely the best choice.
End users don't care what language servers are written in and it's definitely not a mistake to start with a dynamic language, even today.
Of course if you feel most productive with a statically-typed language that's a fine option as well which may result in less technical debt/rewrites later at the cost of initial velocity upfront.
Rather, I believe that people who are concerned about the soundness, consistency and maintainability of their code, and hence favor powerful static type systems, are incapable of prioritising time to market.
e.g. at one end of the spectrum is Java, which everything has to be a class. Even if you want to write a function, it has to be expressed as a static method in a class. In Java it's just not possible to implement ideas in the most obvious way, it has to be done in the Java way.
Conversely, TypeScript was designed to work with JavaScript (which is very dynamic), so it has a very capable structural type system. The productivity penalty is negligible.
That said, my background is mostly Ruby/Python/JS/PHP, so for all I know this is true of many statically typed languages (but from what I read this is not the case).
Still, for those with a background similar to mine I can highly recommend TS as a great starting point for more statically-typed code, precisely because it's opt-in if you want it to be.
Now there is no guarantee that a dynamic language will have those issues more than a static language, but I for one sleep better at night knowing my compiler is doing so much more work for me.
A Ruby API with a good caching strategy is faster than a C/C++ binary with none and it's much easier to implement sophisticated caching strategies in dynamic languages.
> unstable, drains your battery, is constantly offline
Servers don't drain battery. Unstable, constantly offline has no correlation and is not limited to dynamic languages
> but I for one sleep better at night knowing my compiler is doing so much more work for me.
Right, choose whatever helps you sleep at night, but your language/tech choices isn't always what helps everyone else sleep.
Servers don't drain battery, but they cost money, so inefficiency matters server-side as well.
And comparing a fully-featured dynamic language implementation with a less-featured implementation in a fairly weak statically typed language isn't really a productive comparison, is it.
from typing import List
Vector = List[float]
def scale(scalar: float, vector: Vector) -> Vector:
return [scalar * num for num in vector]
def greeting(name: str) -> str:
return 'Hello ' + name
[0] https://github.com/python/typing
[1] https://docs.python.org/3/library/typing.html* numbers.Real / Union[float,int] do not work correctly; I basically can't figure a way to annotate a function that takes an int/float/decimal/etc.
(mypy doesn't think "int" is a valid "Real", and it doesn't think you can add two Union[float,int] objects.)
(mypy has nonetheless been very helpful, and overall I would recommend it.)
It seems like you should be able to just annotate it with float?
... when an argument is annotated as having type float , an argument of type int is acceptable ...
Yeah, those pesky dynamic languages only power some of the biggest sites on earth...
In the many years I've done front-end with Javascript, type-related bugs were very, very rare. Textbook logic as why to use strong types make absolute sense. Yet in the real world, I've had to fight with logic, DOM, UX, framework incomprehension and other types of bugs - not types. Type issues were anomalies among bugs. When they came up, they were the easiest to fix.
Am I alone here? Anyone in the community have concrete examples of type-related bugs that took so much time to required using something like Typescript? Can anyone quantify that?
Wow, really? My experience has been the complete opposite.
Most of the bugs that slip into production have been dumb type errors. Things like accessing a property on an null/undefined value, or on an object that doesn't have that property and unfortunately JS just returns `undefined` instead of complaining (these silent ones can live longer before being spotted).
It's because of these kind of bugs that i've found many JS codebases tend to become brittle to the slightest change, and very difficult to refactor into a good shape. And why i'm seeking statically typed languages like TypeScript on that front at the moment.
Type checking can help you with a few kinds of problems you'll have trying to make changes in those kinds of systems, but you still have piles of problems and it doesn't do anything to help improve the underlying issue.
Static types can help you with some small problems, but that doesn't mean much when the problems you have are big.
Yep, that's exactly the problem :)
The thing is that, without ease of refactoring, it's very difficult to change that big ball of mud into something prettier. In fact, i'd say that without ease of refactoring it's kind of inevitable to fall into that big ball of mud "design" in the long run.
(Note: static type systems are not the only tools to help with refactoring. Good test coverage, style guidelines, a well documented / simple architecture, are of course very helpful too.)
Integration tests ( not to be confused with functional tests / i.e.: selenium ) that test multiple classes in concert via input / expected output give the most bang for the buck, because you know your code works as a whole.
Not sure how that's a small problem unless you never refactor code.
I've heard this same argument from a coworker working on a different project recently working on React/ES6 stack - I check their TFS history and find 3 such fixes in last 2 weeks (and they have reviews before checking in to TFS).
But there was a heavy correlation between type bugs and the kind of code being written. Our transactional frontend apps? Most bugs are browser css issues, weird environment specific edge cases, misunderstandings of the backend, memory leaks, etc.
In apps that are data heavy though, or backend JS apps, its a whole other story. Type bugs all day every day (though a part of it is because we don't do many and they aren't high profile here, they're very light on tests).
So we moved the later to using tests. While it helps a lot, we did end up with a different kind of issues: broken type definition issues and bugs in the type system. Turns out a very large portion of DefinitelyTyped definitions (especially those of the more obscure libs) are broken and you can't trust them, but you lose a lot of time fixing runtime bugs the type system forced you to make. And while they never hit production, there's more bugs than expected in TS itself, and it takes a while to figure out if I'm doing something wrong before I go look at the bug tracker (the issues I hit have almost always been reported already, but I don't expect them). Fortunately that last category rarely cause issues in production.
With types you can test quite less. You still should but test code is the worst code, it turns legacy so quickly.
Something to note though: the example given in the article is not showing any problem in TS. That's how its structural type system works. Both Animal and Bird classes don't have any properties, so the type of their instances is the same as `{}`. If you change the Bird class to something like:
class Bird extends Animal {
song: string
}
Then the line that tries to push a `new Animal` into an Array<Bird> will not type-check, because the types are invalid :)[1]: https://www.typescriptlang.org/docs/handbook/compiler-option...
Another reason i've enjoyed TS is the editor intellisense support. It's really helpful when using a library to get type info in your editor instead of having to google when you forget what a function returns, for example. This is also helpful when you're coming back to code you wrote a long time ago, or a colleague wrote it, and you don't know what particular variables/function arguments/object properties are at a given spot in the code.
The app I did was a financial related app so we do some good amount of number crunching. From calculations, to transfers, and storage.
You won't believe how many type errors we had throughout the stack. It's definitely because of JavaScript's inability to do type checking.
One workaround people did was to do the type checking in the first few lines of the function call, which is how people that still do raw JavaScript, do it today.
function add(a,b) {
if (typeof a !== 'number') { ... }
if (typeof b !== 'number') { ... }
return a + b;
}
This eventually creeps throughout in the code and introduces this code smell.This above can be solved by just using TypeScript.
The other class of errors was with objects that reference other objects - e.g. function takes `loggedUser` parameter which is expected to have property `finishedLevels` or some such and someone sends it `bestFriend` object that kinda looks similar but does not have 'finishedLevels` property.
Most importantly, you have to code differently when writing without typing. It felt as if my hands were cut of at first - I was often in "I would solve this easily in Java just by making interface that would communicate list of needed methods, but cant in javascript because there is no such thing as interface". This is also the likely reason why you do not see many bugs - you probably learned to avoid all those patterns and idioms.
Even more importantly, it really helps with refactoring if you can rename function/variable or change number of its parameters and have all the places (and exactly them) that call that place return error. I can refactor much more aggressively when working with java vs javascript. In java, I spend a lot of time changing existing stuff, when I am tired to do hard work. In javascript it is special thing you do when you are well rested and fully focused.
I am not a Javascript person, but my personal experience has been similar.
FWIW, I used to do maintenance programming on a ~250 KLOC application suite written in C. And nearly all of the "type errors" the compiler caught were instances of using some type T where you needed pointer-to-T or vice versa, which is a non-issue in Javascript.
Lately I have warmed up to statically typed languages, but among all the bugs I have run across in dynamically typed languages, unexpected/invalid/wrong types were very, very rare.
The benefit of good type system - IMHO - is not that it keeps you from putting string where a number is required. That kind of problem happens, but is usually easy to fix. But a type system that helps you distinguish between, e.g., numbers that are temperatures and numbers that are air pressure measurements is worth having around.
EDIT: I admit, C's type system is exactly the most sophisticated one I've seen.
How is that a non-issue? If you don't have unit tests covering your entire code base you wouldn't notice a bug like that until it broke in production.
Having type checks let's you catch obviously wrong things like accessing a Promise return value directly rather than interacting with it as a Promise (i.e. then or async/await).
In C, there is a distinction between a value and a pointer to some value. In Javascript, as far as I understand, everything is a reference, so the specific mistake the C compiler caught would be impossible to make in Javascript in the first place. (Then again, C does not have concept of promises.)
I am not saying type checks are bad or useless. In fact, over the years, I have grown to appreciate every little bit of advice a static analyzer can give me. But among the bugs I have produced using dynamically typed languages, few had to do with using the wrong type.
Oh-oh, too late to edit.
Of course, what I meant to say was: C's type system is NOT exactly the most sophisticated one I've seen. ;-) I like C a lot, but type safety was not its top priority.
Also, the point isn't so much that there is one major, hard-to-fix bug, but that there are lots of small ones that you never encounter.
That's because you're not seeing them. I bet that if you plug your frontend to an error-reporting tool (e.g. Sentry) you will be overwhelmed to see all the corner-cases you are overseeing.
Types are (apparently) crucial for large projects. However, the #1 benefit is speed, which I don't think Typescript can provide.
Sorry I can't quantify any of that.
EDIT I am curious why this was downvoted.
Also, I can load the desktop version of the site in under a second on my phone. IMO y'all should've stuck with some good old fashion HTML and CSS, especially since there's nothing dynamic about Reddit's content.
Hell, you guys could probably get away with responsive styles alone, but I get it. As a business, you find it optimal to piss off your users into downloading an app so you can send them push notifications, dig into their contacts, and find out where they're eating tacos.
Agreed.
I use mobile tethering as my home internet. Currently reddit loads in under 1 second per page usually. The new JS-heavy profile page usually takes 5 seconds or more to load (assuming I'm willing to enable JS to see whatever crap is on one when I bump into them -- usually I'm not...) Note that that's with full bandwidth. When I hit my data cap, I'm throttled to 8KB/s... The current design of reddit is one of the few sites that I can actually reliably load quickly under those conditions! They should seriously think twice about throwing away something that works that well.
Non-SPA related, I also think that many of the touch targets are too small, or work in unexpected ways. Tapping a username collapses a comment, even though there's an arrow next to it. Tapping an image associated with a link doesn't follow the link, it expands the image (even if it is an article link). Tapping the title takes you to the comments, not the article. The only way to get to the content is to click the itty bitty domain title beneath the title. All of these behaviors are different than how the desktop view behaves. For a site that calls itself the front page of the internet, it's getting harder and harder to get to actual content.
The reddit mobile site takes 13 seconds to load on my Nexus 6 over wifi. Then it has the nagware ad to try to get me to install the app, which only has a tiny 'go to mobile site' link directly underneath the large 'continue [to download]' button. Once reddit has finally loaded, every link will then first ask you if you want to view the link the app, before allowing you to continue. Meanwhile the UI, while cleaner, is debatably worse off UX wise as everything is now small and laggy.
So to summarize, it is terribly unperformant app, filled with dark patterns and dubious UI improvements.
Works very well otherwise.
The compilation step is a major pain. Even after using it for several months straight, I feel like I'm in a constant battle with the compiler. It's slow and difficult/annoying configuration problems keep coming up from time to time. It slows down my debug cycle and the compilation delay makes me lose my train of thought. I used to love using console.log() to quickly test an assumption in JavaScript; you cannot do this with TypeScript (it's not practical given the 5 to 20 seconds compile time); you have to use the debugger every time and step through stuff (even when you have a very good idea about which specific variable you want to check) - It's extremely cumbersome.
I have gone back and forth from dynamically typed languages to statically typed languages many times for years and I've spoken with engineers who used to be Java developers for many years, then switched to Javascript, then TypeScript and they shared the same thoughts as I did. TypeScript is slow and restrictive in a way that is unnecessary. It's got Microsoft all over it.
Also it forces all developers to use bulky commercial IDEs like WebStorm because you rely more on code completion to help you figure out the right types. You can say goodbye to Atom, Sublime and the rest... Atom's TypeScript plugin is not good enough unfortunately.
At my previous work, even developers who said that they liked TypeScript secretly didn't like it because they used the 'any' type Everywhere.
I wonder if the people who are making this decision have actually tried TypeScript themselves for any decent amount of time on a decent sized project. I don't think they know what they're getting into.
I decided not to renew a lucrative contract at a finance firm as a front-end developer in part because I did not enjoy using TypeScript every day.
Have you ever used `tsc --watch`? First build can take long but modification and rebuild takes < 1s.
> you have to use the debugger every time and step through stuff (even when you have a very good idea about which specific variable you want to check) - It's extremely cumbersome.
You don't "have to" use the debugger if you prefer `console.log` all the way. However in the debugger there is a "watch" tab for inspecting specific variables.
> Also it forces all developers to use bulky commercial IDEs like WebStorm because you rely more on code completion to help you figure out the right types. You can say goodbye to Atom, Sublime and the rest... Atom's TypeScript plugin is not good enough unfortunately.
VSCode? https://code.visualstudio.com/
I've worked on TS on large existing projects as part of large teams. In my last project, we did have some sort of file system watcher but it still took > 10 seconds on average to compile. Launching the project from scratch took longer than 1 minute. From time to time, I did have to relaunch the whole app; usually for a different reason every time.
The biggest gripe I have is that Chrome debugging is hell, because sometimes it will recognized the typescript, sometimes only the javascript. I have hit Ctrl-P many times to "establish" mappings between files running in IIS Express and local files. Miss and hit.
I use console.log all the time so I don't understand your comment in that regard. It works perfectly fine with Typescript.
I code typescript for Angular 2/4, and although yeah, the aforementioned debugging pains are annoying, the time saved on having types to enable linting and strong predictable variable comparisons, is much greater.
Also, needing console.logs everywhere should be discouraged. Your code should be clear enough that you don't need a console.log debug line to print the boolean result of a comparison, for example. This is the whole point of typescript like I said, to make variable comparision and management easier so that you don't need that console.log line...
Developers from statically typed backgrounds just don't seem to understand this use case. It's the quickest way to find an issue when you have a good idea of where the problem might be.
AFAICS the Typescript types ecosystem is bigger simply because Typescript has been advertised to devs coming from a background of a statically typed lang, and they cannot imagine not using types, thus they drown in them.
Flow on the other hand appeals to those that want types primarily in their own codebase, and come from inferred/dynamically typed langs, where you gradually add static types starting with key sensitive parts in your codebase e.g. Erlang http://learnyousomeerlang.com/types-or-lack-thereof
The example that I was given was C++ and C, but I think TypeScript with it's gradual-typing approach is forced to remain potentially as bad as JavaScript itself - that is, if you're feeling weak and want to "get shit done", you can bypass all the goodness that TypeScript undeniably offers you.
For a language like Elm, the type-system is invariably gonna have your back - a value-proposition I think means a lot more in practice than some self-proclaimed pragmatists realize :)
"Ghost Of Christmas Future Taunts Children With Visions Of PlayStation 5"
http://www.theonion.com/article/ghost-of-christmas-future-ta...
There's a project on my plate right now that when I saw the requirements and specs, I immediately thought, wow, Elm in a year from now would be absolutely perfect for this.
But it's just not there yet, so I'm exploring things like Typescript that have the advantage of the Javascript ecosystem beneath it. But I really cannot wait for Elm to be production-ready across the board and not just for specific use cases.
> One of the worries we had with Flow was that it was built to solve specific needs at Facebook and that its future would be determined by that scope.
if you replace [Flow/Facebook] with [Dart/Google] , I guess you could make the same point.
Because Dart is a different language. Typescript is (mostly) Javascript with type annotations, so there is nothing new to learn. In theory, you can just change the extension of a file from .js to .ts to convert it to Typescript.
Does this make sense or is it feasible to skip learning JavaScript and jump directly to TypeScript?
That being said, I don't see why you couldn't learn them concurrently; you can learn the basics of TypeScript and then simply rewrite any relevant JS example code into TypeScript to learn JS code in a TS context.
Edit: I should also point out that integrating with any JS libraries may require you to install the '@types/' package alongside it to maintain type-safety. For example, if you're using jQuery, you can install the '@types/jquery' package which will expose all the type information for the jquery package.
On the other hand the upside, and a very big one, is that if you set up the relatively simple TS build process, you automatically get all the ES2015+ stuff for free, even without needing to figure out Webpack and Babel and the like (with some caveats front-end-wise, primarily Promises and Fetch).
If you want to develop an in-depth understanding of the language, I suggest reading through the ExploringJS [0] series. It covers pretty much every single edge case and detail. You don't have to read each book cover-to-cover, you can just skim parts you're familiar with.
To give you an idea of how awesome it is... Exploring ES6 is my go-to reference for anything related to ES6. When I first discovered the book I'd already been writing ES6 code for a while, and I thought I knew everything there was to know about it. But upon reading it, I was blown away by how many things I hadn't been aware of.
It's definitely feasible and it will even save a few headaches. It's especially good for learning the API because, of course, it provides intellisense.
I find myself downloading type definitions for JavaScript libraries because it's often a quicker form of documentation than the library's official docs.
> I was more worried about not understanding other code and libraries that are written in JavaScript style.
There isn't much stylistic difference; TypeScript is not a huge departure from JavaScript.
You can learn one before the other and a lot of the skills are transferable.
That said, I suspect it won't be too difficult, and quite worth your while, to learn 'idiomatic JavaScript' if you have experience with at least one other language. And especially with ES6 (which is 'included' in TS), if you have any experience with Ruby or Python you'll be fine with JS and it might even be a relatively pleasant experience.
However, on the other hand, I think that a good, experienced developer has no problem with that. The bugs that the experienced developer "fears" have nothing to do with type errors, which at the end are rather easy to solve...
I assume you're not claiming that experienced developers never have runtime exceptions, or that they're always easy to solve.
Not sure how you define "experienced developer", but I think you got it backwards.
A good type system enables you to structure your code in a way that most sublte bugs are "converted" to type errors. That's the magic of types!
Your type definitions aren't just some syntactic sugar so that the type checker finds some typos.
Your type definitions are a vital part of the code base that you design to protect it from changes that introduce subtle bugs - the kind of kind you can easily foresee when you wrote a particular module, but which others (or yourself after 6 months) won't be aware of. This is especially important on refactoring, but also super helpful for non-trivial extensions.
In that sense the types are like unit tests. Although they are less flexible than unit tests (so they are no substitute), they make most of your unit tests unnecessary and are shorter and easier to write and to maintain than those unit tests. Most importantly, however, they "test" all cases, statically at compile time, not just the specific cases of your unit tests.
A language with strong typing (which additionally can be a dynamically typed language, something that many people are not aware of) will catch any of such type errors, without having to bother adding type specifications/signatures everywhere in your code. Thus, those are bugs that are trivial to solve.
And this, to paraphrase your post, protects your code from changes that introduce subtle bugs.
You can also have a language that is statically typed but that has weak typing! Which language? C. And i think everybody knows the extra effort needed to keep a C program bug free. And this not only due to lack of automatic memory management!
I have been programming for most of my life, that is about 23 years of programming on where 20 of those years were using statically typed languages, including many years programming on large, business-core systems on Java and C#. I since have gone to dynamically typed languages and never looked back. You just need strong typing, that's enough.
You might be able to prove more assuring properties about your program with a test suite.
When the GP said:
> A good type system enables you to structure your code in a way that most sublte bugs are "converted" to type errors. That's the magic of types!
I am almost certain that s/he meant type errors uncovered without actually executing the program. In a dynamic strongly typed language, you will need to execute the program and force it into these errors - presumably using a test suite.
> A language with strong typing (which additionally can be a dynamically typed language, something that many people are not aware of) will catch any of such type errors, without having to bother adding type specifications/signatures everywhere in your code.
A static type system does not need type specifications/signatures "everywhere" in your code. In Java and C#, it does. But many modern languages, TS included, can infer static types to a large extent.
But the type-safety you get with these kinds of static languages only catches a few trivial bugs. There are also some situations where TS complains where it shouldn't, for instance it doesn't handle JS' built in reduce function very well.
In the end, it's a trade-off between the benefits and added costs. It is in no way a given that adding static typing to your JS project will be beneficial when all factors are considered.
There are so many situations where my input is strings (JSON through various API's) that should get turned into just integers, floats or (string) constants shortly after being consumed. Using TS types from this point onward promotes discipline to do so on my part, removes any ambiguity going forward, and alerts me if I treat these values as strings or any other wrong type (which commonly happens to me, at least, when using vanilla js).
And as you say it's also important to setup some boundaries so that bad values can't travel to the other end of the program before you notice, which is a pain to debug.
I like to make value checks on module boundaries, but do much fewer checks inside modules. I typically do this using assertions. Optional types can be a way to do it with less noise. But they still can't replace asserting arbitrary invariants, like invariants involving multiple values.
It's an extremely conservative language, offering little to nothing interesting that would make anyone switch from other solutions.
The ecosystem doesn't help it either:
For the frontend, it's stuck in a middle ground where it requires a JS interop layer (unlike TS, where it's typings are just an extra) but doesn't offer anything significant like Elm, BuckleScript, F#, ClojureScript and so many other great languages do when it comes to expresiveness. It doesn't even have algebraic data types, something TS does.
For the backend, it competes against almost all the frontend languages (due to node or native) as well as the big boys with huge ecosystems, variety of paradigms and amazing performance.
For mobile it has Flutter, which competes with Xamarin, Kivy, Qt and other bring-your-own-widgets solutions (deal-breaker for some apps and teams). In this case, Flutter is something I wanted to try out since those other solutions left me wanting and so did React Native, but Dart being such a lackluster language completely put me off of it, now having to turn to native with Kotlin after all this time looking at (and somewhat helping develop) the x-plat ecosystem.
I don't doubt that Dart will remain healthy for a long time due to Google's investment in it, but honestly, even if Fuchsia ends up being Android's succesor and Flutter ends up as its graphical toolkit, I'd instantly start looking for languages targeting the Dart VM or native interop.
Could you please give specific examples of where you felt RN let you down? (Also, did you use Expo or vanilla RN?)
Thanks
Huh ? Compared to JS - Dart seems like a heaven. Don't known Elm - but looking on syntax it seems it's not so easy to pick up as for someone with Java/C# background. It's true Dart is not another fancy lang - it's very pragmatic.
It looks like a great language, but I think it hasn't done well on the web because it has very poor interop capabilities with JavaScript and its ecosystem. I'll note that I haven't dug that deeply into Dart, so maybe there's some great resources I've simply missed so far.
TypeScript and Flow are both great options because they work completely with existing codebases. They can be adopted gradually and integrate well with the ecosystem.
Another language that looks promising is Reason [0]. It's still very young, but they seem to be working hard to create an awesome language with a great interop story. Check out their getting started [1] guide. Most of the info related their interop is in the BuckleScript User Manual [2].
[0] https://facebook.github.io/reason/index.html
[1] https://facebook.github.io/reason/gettingStarted.html#javasc...
I for example believe that readability matters, and typescript is not that, compared to Python or even coffeescript.
And I really don't like how all the cool new languages lack significant whitespace.
You can probably tell I'm a Pythonista. A Pythonista always pays his technical debt.
So, I think we can say that you don't choose static typing in order to write fewer bugs.
I've worked in lots of code-bases, both static and non. Indeed, the bug rates are fairly consistent across them. The worst code bases I've seen (from a maintainability perspective) were actually old C++ and Visual Basic ones.
Refactoring is easier in statically typed code-bases. But, in my experience, it's not significantly better. What makes a bigger difference is immutability, functional purity (within reason) and a preference for obviousness (as opposed to, say Ruby-like magic which makes me pull my hair out on a semi-daily basis).
[1] https://dev.to/danlebrero/the-broken-promise-of-static-typin...
And still, everybody agrees, according to the down votes. That is frustrating!
Significant whitespace is redundant in the face of auto formatters. The latter are becoming more popular, and rightfully so.
I tried finding what TS can do now, and figured out type-level tuple iteration, among a few others. The current roadblock seems to be getting function return types. Progress, for anyone interested: https://github.com/Microsoft/TypeScript/issues/16392
At this point I'm amazed how close we are to typing anything, despite having only 5 (!) type-level operators, with their respective warts.
Fast forward several months and I picked it up again. I've now been writing everything that I would have done in JS in TypeScript and have built several applications using both Angular and React entirely in TypeScript. I've also sold my teammates on switching to the language.
When I was (stuck) writing JavaScript, the frustration factor was high for me. I'd get nebulous errors[0], hunt around the line it referenced, swear a little, and trace the code back to the cause. I would wildly estimate that one out of ten attempts at blindly running my code would succeed[1]. Even on unit tests, which had a higher degree of success since they were testing much less, still had a much higher fall-over[2] rate than I get in typed languages that I enjoy. The addition of types, which adds a little overhead, flipped that over. I am still surprised every time I refresh a page that uses code I'm modifying and it loads. The reduction in time spent debugging (and swearing) makes me enjoy the language more every day that I use it. It's even left me longing when I am writing code in other languages (mostly Java/C# these days) and features I have come to really enjoy (union types, intersection types and to a lesser extent the duck-typing nature of the language[3]).
Since crapping on any language, or feature/lack of feature of a language tends to become a religious war fought with verbal violence, allow me to admit a few points: Traditionally, I avoided JavaScript and jobs related to it. Personally, I hate the language. This means I've spent considerably less time researching all of the best practices/techniques for surviving those cases where I have to write JavaScript. I started in C and Pascal and prior to a few months ago spent 99% of my time in typed languages. I am an advocate for unit testing[4], but I find test-driven development requires me to work backward and it's less productive for me. I'd imagine that if I went all in with TDD, I might see fewer of these problems, but many of the best practices for JS development are best practices in the languages I am more proficient in and despite following these practices, JS design led to these practices being less effective at reducing bug frequency. Yes, I could just be a yelling 'get off my lawn' because I'm unwilling to change[5]. But I've also worked closely with highly-skilled JS developers who could rapidly produce incredible things as a result of its flexible, dynamic typing. Incredibly, though, one of those 'huge JavaScript advocates' was the one who told me to give TypeScript a chance late last year. Though he would always fight me on the "dynamic vs. static" thing, his argument was that TypeScript's type system was light-weight enough to keep out of his way while strict enough to lower the frequency of self-inflicted foot bullet-holes (paraphrased). Really, though, ... two nulls, asinine boolean implicit conversions necessitating code like double-bang and === / !== operators[6] should be enough.
[0] Often depending on whatever framework I was using, but I've rarely found one that returns an error that results in a really obvious 'oh, I know what I did to cause that'
[1] I like to check that a component renders visually appropriately and often do a quick check before I've written all of the required unit/integration tests to make sure it's rendering accurately (right data/right result).
[2] As in, something fails badly enough to stop execution rather than just failing on an assert for an incorrect result.
[3] It's a love-hate thing for me -- the result is being able to reduce boilerplate making mostly-compatible types interact, but the down-side is that the compiler giving a pass to "A=B" when "A" has at the properties of "B" results in some subtle bugs that have already bitten me more than once.
[4] Though I don't buy into TDD (either before writing the code or after) solves most of the issues of dynamic typing. I've had more than a few tests fail because of a type-related issue...in the test.
[5] Except that I love learning new languages and 'keeping up' and have found that as I've aged, I can pick up new languages far more quickly than I could in my early 20s... [plug]RUST![/plug] I'm also not terribly old, nor terribly sensitive about being called an oldster.
[6] I don't recall who, but someone was once reading code out-loud and said "if action fuckin' equals 'ADD' and payload.Length doesn't fuckin' equal zero". Adding in the fuckin' every time he encountered the "really, really [not] equals" operator. So that is how I mentally read those. I'll never forgive him (sorry for the swears ... and doubly sorry if you end up reading code like this as a result).
This sounds like a total non-sequitur.
> Typescript also came with a lot of “social proof” and better assurances about its longevity There are several large projects using Typescript (examples include VSCode, Rxjs, Angular, and Typescript itself),
While I agree with the sentiment, I don't understand why they include "Typescript itself" in this list. Isn't that a circular argument?
Are client-side only JavaScript applications not handled well by the likes of Google et. al. today? I was under the impression that they run a full JS interpreter.
And none of them passed the test of time.
So I think I made the right call by not adopting them super early.
I think I'm going to do the same with Typescript. Hopefully static typing will be adopted by ES.Next and then I'll port my programs to it.
All the new product is just awful. I feel sorry for them.
From the top of my mind https://github.com/styled-components/styled-components.
Everything updated in 2017 (so from react-float-anchor and later) has flow types included.
however, why did you choose this weird cursive-ish monospace font? and...where can i get it?
I assumed this font was for marketing purposes only; regardless, I also assume that they let their devs customize their own IDEs look-and-feel, so to each their own.
You either understand the code or you don't.
... It's probably not worth $200 though.
Take nothing away from TS but the mobile Reddit is all the proof in the world that no matter the language, the paradigm or the ecosystem, someone can still use it to turn out a horrible product.