Deno will stop using TypeScript
startfunction.comThere are so many uninformed and misinformed comments on this post. Please read the design doc[1] before commenting if you assume the Deno team is doing it wrong, or hasn't ever considered some obvious solution you came up with in 0.7 seconds.
[1]: https://docs.google.com/document/d/1_WvwHl7BXUPmoiSeD8G83JmS...
First paragragh of that document:
> Update June 10 2020: I saw that this design doc was being discussed more widely. Most people don't have the context to understand this narrow technical document - it is only applicable to a very particular, very technical situation in the internals of Deno. This is not at all a reflection on the usefulness of TypeScript in general. It's not a discussion about any publicly visible interface in Deno. Deno, of course, will support TypeScript forever. A website or server written in TypeScript is a very very different type of program than Deno - maybe much more so than novice programmers can appreciate - little of Deno is written in TypeScript. The target audience is the 5 to 10 people who work on this particular internal system. Please don't draw any broader conclusions.
I mean, the design doc is wrong. Instead of
you can just useObject.defineProperty(HeaderImpl, "name", { value: "Header" });
to avoid creating a conflict between the header type declaration and this header implementation, since that way the type will be locally constrained to the class expression and only the variable gets out.export let Header = class Header { }> Who knows if this kicks Header out of some optimization path in V8
It doesn't.
---
Forgive me for being suspicious of the whole thing because a couple of the rationalizations don't make sense, I'm sure there are some valid points raised there.
Gotta appreciate the part implying that anyone who finds this document amusing is a "novice" programmer.
I thought the "novice" programmer remark was a pretty cringe-worthy comment.
The original reasons listed by Deno for removing TS had the undertones of "senior engineer who hates certain tech because they didn't use it right". Naturally, their response was to say "you probably don't understand cause you're a novice".
I can sympathize with their issues. TS compiles are slow as fuck, and if I could find anything that was just as nice without the long compiles I’d switch in a heartbeat.
But I don’t think I’d ever want to go back to plain Javascript.
There are efforts to provide faster compilation times: - https://github.com/evanw/esbuild - awesome, I use it for most of my ts projects - https://swc-project.github.io/ - also awesome, but has some bugs
Esbuild is cool, but if it doesn’t check the types then using Typescript is a bit pointless in the first place.
Guess a combination of esbuild during development, and tsc during commit would be the best of both worlds.
Not necessarily, TS issues are found in the editor which is where most of the use is. I don't test types only on compile but usually through VSCode itself.
Thumbs up for esbuild, it's awesome.
My sentiment as well.
That passage didn't say anything about finding the document 'amusing'.
That document is not particularly enlightening either.
> we're removing the types from internal code and making it pure JS. this reduces complexity and helps us ship a faster product
Yeah, because dropping static types from 10K lines of code is definitely not going to be a maintenance nightmare in the long run.
But perhaps this is something beyond the simpleton comprehension of us novice programmers
> Yeah, because dropping static types from 10K lines of code is definitely not going to be a maintenance nightmare in the long run.
My personal experience is that there’s a size threshold where static tying becomes more useful. Below this threshold, the problems solved by static types are still mostly tractable by humans and things like linters. The threshold is different for every program and set of developers.
10K lines is small enough IMO.
> But perhaps this is something beyond the simpleton comprehension of us novice programmers
That’s just flamebait, the comment is better without it.
It was your GP who introduced the word "novice".
It’s not the word, it’s the sentence.
> That document is not particularly enlightening either.
Here are some key words that many kibitzers here could benefit greatly from internalizing:
> > The target audience is the 5 to 10 people who work on this particular internal system.
> Yeah, because dropping static types from 10K lines of code is definitely not going to be a maintenance nightmare in the long run.
Are you one of the people responsible for maintaining those 10KLOC?
> But perhaps this is something beyond the simpleton comprehension of us novice programmers
I believe Ryan Dahl would admit to having made more mistakes in large system design than most of us will ever have a chance to. Who knows, he may have picked up a thing or two along the way that most of us haven't.
This could also just be an internal product decision that really doesn't affect anyone outside the core project team, while some of us here are projecting way too much onto it.
> maybe much more so than novice programmers can appreciate
Okay, unsubscribe. This is not the tone you use to interact with the community. This is brash, elitist hogwash.
This is gonna be an unpopular opinion but as someone who learned to program in loosely typed languages, I have never seen the TS appeal.
TS feels like something that was created to lure programmers who couldn’t wrap their heads around JS loose nature. Almost like it was created to convince Java and C# developers to use JS.
It have never felt about it like something that would make my code better or more organized. It definitely slows me down with very little benefits in return. (Again, can’t stress enough that this is a personal opinion based on personal use cases)
I appreciate that it forces me to be more intentional about organizing my code but I also get that when I use frameworks.
Of course I also appreciate when I can identify that an error is coming from a type mismatch, but as I said I learned to program in loosely typed languages first, so I never created that concept of defining types in my head. I’m always extra-aware of types mismatches in my JS code and is usually the first thing I check when something goes wrong. But I have never felt the need to have a way to explicitly define the types that I’m working with. I honestly fail to see the benefit when a large amount of code that you have to interact with (libraries and such) was written in classic JS.
Once again. Probably unpopular opinion, so I don’t mind the downvotes.
You don't have to write as many tests when you use static typing, because your method contracts are solid.
You can refactor your entire codebase with a few operations and don't have to worry about anything breaking.
Is your timestamp in seconds? Millis? Is it a duration? Does it have a time zone?
Have you ever written a method that returns more than one type of thing? Or had polymorphic inputs?
Where are your dynamically dispatched calls even used, and how do you know you modified them all?
One of the most common operations in building new features is plumbing new state through the system. Types are there to help you in such perilous times.
Types are refreshing and reassuring.
You don't have to write as many tests when you use static typing, because your method contracts are solid.
People often say this, and I don't get it. What JS tests are you writing that become unnecessary in TypeScript? I've used a fair amount of TypeScript and plain JS, and end up with similar amounts of tests for each. With JS, I almost never want to verify only that a value is of a specific type; I want to look at its contents, which means I'd need to write the same test in TypeScript.
Let's say you have a method that takes a thing:
How many different possible representations of a 'thing' do you have? A json object? A class object with behaviors? A database id? Some sort of natural key like a SKU? A URL? Is it a metric or imperial thing?function doSomething(thing) { ... }You need integration-level tests around every method call to ensure that caller and callee agree what kind of 'thing' representation to use. Type systems can eliminate this class of bug entirely.
I never throw inputs of random types to my functions. Actually that could be a good idea, some fuzzying at the public API level could catch some bugs and attacks. But not at unit test level. If a function expects an integer argument I test it with integer values. That in Node, Ruby, Python and Elixir. I never saw anybody doing something different. Well, if we wanted to enforce types we could use any static typed language out there.
Let me offer you an example that comes from the Python world (I see these errors every few weeks and every single one of them means that some dependency of my code has somehow broken).
1. The library makes an assumption on a type (in the case of Python, that's typically "there's only one type of strings", "there's only one type of streams", sometimes "there's only one type of numbers", etc.). Since the language is loosely-typed, there's no API barrier that checks this, it's all duck-typing.
2. Tons of code is written based on this assumption.
3. Assumption changes. In this example, this happened with the Python 2 => Python 3 migration, but it also happens once in a while with smaller version increments of either Python itself or Python libraries.
4. Where is the assumption used in your code? Well, if you're lucky, you're going to find out once a piece of your code throws an error because it's attempting to use a method that doesn't exist anymore. If you're not lucky, the behavior of your code has changed subtly.
In the loosely-typed world, the only way to avoid this is to have very strict boundary checks. Which means basically manually implementing subpar type checking at the borders and unit tests and/or fuzzing just to ensure that your mock-type-checking actually does its jobs.
Of course, you can often get away without doing this as long as your code is for internal use only. But if you're writing a library and if you want your users to be able to troubleshoot problems without too many difficulties, you're doing manually what the compiler is doing for you in a statically-typed language.
If a function expects an integer argument I test it with integer values.
Metric or imperial integers? Your unit tests failed to prevent this $300 million blunder:
https://www.wired.com/2010/11/1110mars-climate-observer-repo...
But more commonly what is going to happen is that someone (two years from now) is going to change a 'person' parameter from legacy SSN to database id and some users are going to get "you don't exist" when they show up at the hospital to get medical service.
You're right though, most folks in the JS/Ruby/Python ecosystems don't do this kind of testing. It's a recurring joke:
https://www.google.com/search?q=2+unit+tests+0+integration+t...
I think the "metric or imperial integers" argument doesn't really work as an advertisement for static typing: A domain specific unit checking type would have worked just as well in Python as in any mainstream statically typed PL, but commonly people use just plain integers that would have failed the same way in a ST PL.
The inputs shouldn’t be “random”, but the idea is that you should provide an input distribution that’s roughly representative of your expected distribution of real-world values (+ some perturbation to find edge cases).
As for frameworks in the languages you listed...
Ruby and Python: https://github.com/HypothesisWorks/hypothesis
Elixir and Erlang: https://github.com/proper-testing/proper
Node and JS: https://jsverify.github.io/
As for real world use-cases, imagine you’re writing a program that accepts timestamps as input and has to implement branching, requirements-defined business logic based off of them. When you’re writing your unit tests you can use the requirements to select timestamps that are “known good” and “known bad”, but it’s hard to explore this state space on your own.
Same thing goes for handling unexpected inputs to certain functions. You probably don’t want to check _every_ type of input for _every_ dynamic function, but it might make sense to make sure that certain “entry points” to your program fail in the expected manner when they get poorly typed input.
How about a map of options where some of them are mutually exclusive? Without union types you have to write test for that.
You need integration-level tests around every method call
Sure, but you need those tests anyway to verify that your code actually works. I agree that type systems reduce the occurrences of some classes of bugs; I'm only disagreeing with the claim that they reduce the amount of tests you need to write.
I used to agree with you, and somewhere in my comment history on HN you’ll find similar comments to yours. But I think I was wrong.
I recently ported some (quite complex) code I wrote from JavaScript to Typescript. The code has about a 2:1 test to code ratio, and a fuzzer for correctness. While porting, I ended up adding a couple “useless” assert(typeof x === ...) calls to quieten the compiler, which felt useless because my code was correct. Lo and behold, the assertion tripped in my test suite - apparently I was sometimes treating a string as an object and didn’t notice. Which was a serious issue; and could end up being a security problem for some people. My fuzzer didn’t find it because it never occurred to me to add string method names in my random data generator.
Generally I find that the bugs that are easy to find with tests and the bugs that are easy to find with static types are different. You can eventually find all bugs with a sufficiently large test suite; and with enough PhDs you can apparently formally prove everything. But you get the best bang for buck with a little of each. A few tests is much better than no tests. But in the same spirit, I find no matter how big my test suite, there’s a good chance static types will improve my code.
Typescript is far from perfect, but I sleep better at night with a type checker checking my code.
Generally I find that the bugs that are easy to find with tests and the bugs that are easy to find with static types are different.
I don't think we disagree much. As your experience shows, trying to replicate type checking via unit tests is almost always impractical. Which means the tradeoff of not having static typing is not that you're writing more tests, but that there's an increased chance of bugs.
And I agree that once a JS project is large enough to have a build process, the benefits of TypeScript almost always outweigh the costs. I'd even like to see JS interpreters allow and ignore TypeScript types, so you could use it without a build step.
>> How many different possible representations of a 'thing' do you have? A json object?
Why would you design a function in such a way that one of the arguments can represent so many different things? The problem here has nothing to do with testing. The problem is that the function itself is poorly designed.
If anything, the difficulty of writing a test for such a function would in itself be an indication that the function needs a refactoring.
It's not the function parameter that has multiple representations, it's your app. The function takes one representation - let's say a numeric id. That doesn't help the client of your function, who could pass in a database id, a database record object, a json object, some sort of natural key, etc... all of which plausibly will match an untyped parameter named "thing". And your function may change its contract someday.
> With JS, I almost never want to verify only that a value is of a specific type; I want to look at its contents
We're pretty deep down in abstract discussions here and I have no idea what your code looks like or what it does, but I think it's helpful to point out that knowing the type means you already know the contents to some extent.
The way I see it, checking if a value is what you expect is always good, but if you additionally get an error automatically because your number is now suddenly an e-mail address, or the function you wrote that expects phone numbers suddenly gets a name instead, in my mind that's "built in testing". It doesn't make other testing unnecessary but it sure raises the bar for cleanliness -- which is especially useful when you're working with other components that aren't JS where types do really matter (like databases, for example).
Forget about the whole testing thing. In a way it’s a red herring. Let’s instead talk about refactoring (this is related to testing but not in the way it is being framed in your comment or many others).
Idk about you, but when I’m sussing out the behaviors of a complex application it can take numerous iterations over different possible types and shapes of the data in order to come up with something both robust and performant.
The single greatest benefit of languages that afford static analysis is that, when I change the shape of some piece of data where it is defined, my editor lights up like a Christmas tree and informs me of every place in my code that was just broken! This is extremely useful for being able to quickly iterate on features. I don’t have to remember all of the calls sites dependent on some API. It allows me to confidently make (sometimes large) changes to my domain and know for sure which pieces of code might also need to be refactored.
I’ve worked in codebases where the confidence I’m describing above does not exist, and what happens is a lot of defensive programming and wasted effort (and time!) dancing around new implementation because no one wants to change anything. Changes tend to become “append only” (we can only add to the interface) because it’s hard to know what’s going to break if you actually change it. This can be okay most of the time, but sometimes new requirements... well... require new approaches.
The above is related to “testing” insofar as I don’t need to test where pieces of code depend on one another in order to know when their contract breaks. But the benefit is not really about testing at all. It’s about work flow. It’s about velocity. And it’s about freedom.
> With JS, I almost never want to verify only that a value is of a specific type; I want to look at its contents, which means I'd need to write the same test in TypeScript.
If such (refactored) method is being called from code that's not covered by tests, the bug may not be discovered until it blows up in production. With static typing it would be caught at compile time.
If such (refactored) method is being called from code that's not covered by tests
Well there's your problem :p
I agree that if code has no tests, it's more likely to be correct if it's in TypeScript than JS. But I don't consider that an acceptable bar, so if I'm doing your code review I'm going to ask for tests in either case. And once you have tests that verify the behavior of the code, you're not getting much incremental benefit from type checking.
Unit tests can only prove the presence of bugs; they can never prove the absence of bugs. Only a typechecker can do that (provided an appropriate implementation). E.g. here is an AVL tree that is verified balanced at the type level: https://sketch.sh/s/C7Afz38jtFRMTkkydeBgUA/
No unit tests needed to show that it is balanced :-)
Personally I have two issues with TS as it exists today. On the one hand I’m reticent to add a transpiler/compiler step between code and the runtime unless there is a very very compelling argument. On the other my perception of TS is that is a tool that removes friction between the language (JS) and tooling without really addressing anything core to the language itself. Everything people sum up as pros of using TS generally end up in a bucket in my head labeled “compiler work to remove friction”. I actually use that friction to improve my codebase, in the instances that some sort of type error happens usually is bringing to the surface an related problem/business domain assumption on my part that I need to address upstream to a conceptual or logical off code layer. Some of what TS offers I get around by being very attentive to providing good jsdoc annotations which requieres disciplina and work- so I see the value brings there but the price I pay for that convenience is to high.
Usually what I do is that once a project has reached a point of maturity and the requirements merit it I move parts of it to a typed language (go). That’s for things that need to be both performant and maintenable long term without much effort.
I actually benefit from that rewrite in that I have yet another chance to review assumptions and address higher order
> my perception of TS is that is a tool that removes friction between the language (JS) and tooling without really addressing anything core to the language itself.
I don't understand what that means. How is TypeScript removing friction between JavaScript and tooling? That doesn't make any sense. TypeScript is a typechecker and a language that compiles to JavaScript.
I’d say that TypeScript removes friction in the sense that you can use autocomplete fairly easily with it, out of the box. Using autocomplete without type annotations is pretty hard.
OK but then that's ... not actually a criticism? And when the person I replied to says, 'doesn't address issues of the language itself', that's not actually even accurate. TypeScript addresses several large sources of errors in every codebase, like null or undefined errors.
Also, things like automated/safe refactoring, jump to definition, find all usages, etc.
Forgive me, but when I program I know what the variables I am working with are doing, and what kind of data they are storing. That’s the least of my problems. I don’t write a big mess of code, I’m constantly working iteratively on a small piece of code to make it perfect. Usually first pass is to make it perfect, then I refactor it right away to make it readable. I work that way, function by function.
I never have the class of bugs in my projects that people seem to laud about typing to solve. It’s kind of ridiculous to me and cumbersome and makes certain dynamic programming concepts difficult or impossible. I don’t want to give up power just because other developers are sloppy.
I want my code to be readable, and succinct. A lot of times that requires creating functions dynamically at runtime or some other such thing that would void the benefits of a typing system anyways.
I recognize that in working with a team where people have other styles, varying attention to detail levels and skill, they can’t all be trusted to produce bug-free code without the constant nagging and overhead of a pedantic type system.
My solution is not to employ another piece of technology to solve this problem, rather it’s just not to work with those people.
If you can’t write dynamic code without a bunch of type errors at runtime, learn to be a better programmer first before blaming the tools.
What a pretentious comment, everyone makes mistakes and everyone can write a big mess of a code eventually. The benefit of typesafety is how easy we can spot that and recover / rewrite when needed.
> Forgive me, but when I program I know what the variables I am working with are doing, and what kind of data they are storing.
How many times has six-months-hence you cursed you for this attitude?
Be honest.
Never. This is why we write small functions that, as much as possible, depend only on their inputs and avoid mutation. Code becomes simple to reason about. You don't need to worry when composing these small pieces like you do when passing mutable objects, using out variables, etc.
See, that's interesting. 'Cause I do write small functions, I do avoid side effects, I do avoid mutation--and writing code in dynamically typed languages still bites me when I'm forced to do it. (It isn't really any faster to write, either.)
So you could be leaps and bounds better than me. Or you could be--let's be generous and call it "optimistic to a fault"--and retrofitting to a narrative about Good Programmers Don't Need Guardrails. And, TBH, I see a lot of people who are the latter and very few who are the former--and most of that very few tend towards statically or at least optionally typed languages by default. So forgive me if I don't believe you.
Anything to justify not learning a new language.
An experienced developer I know with a dead simple function fell for the classic 10+20+30=102030 bug the other day. Had it not been noticed in production it would have been very costly. It was an edge case he had not encountered in the wild, but had thought to handle just-in-case. Integration tests missed it too. Sure, good unit tests could have caught it, but Typescript would not have allowed it in the first place.
> Forgive me, but when I program I know what the variables I am working with are doing, and what kind of data they are storing.
Will you in two years? Will your coworkers? Will the contractor who has no context for the code understand it?
Like variable names, types convey information that are crucial to the understanding of your application.
Under the hood, there are "types", even if they are weak, so you'll need to know about implicit typing anyway. Making them explicit is both a way to test correctness and a way to document your code.
'Forgive me, but when I program I know what memory I allocated, whether they are accessed within their proper bounds, and whether they are all deallocated properly.'
Meanwhile: https://www.zdnet.com/article/microsoft-70-percent-of-all-se...
'Percentage of memory safety issues has been hovering at 70 percent for the past 12 years.'
And this is not just Microsoft–it's a pretty consistent finding across industry, that when programming in C/C++, memory safety issues make up around 65% to 70% of all issues.
What this tells us is that people in general can't guarantee the safety of their code, but an automated checker can.
I suppose you are also going to tell us that after you’ve fitted all of those perfect functions together into that perfect program, the requirements have never changed.
And I suppose when those requirements never changed you never had to rewrite lots of these perfect functions or resort to “append only” programming in order to make sure regression was impossible instead of making large changes in place.
Forgive me, but it’s clear you have never worked on a program of any consequence, so it’s hard to read your comment and do anything but wish you the best while also completely ignoring its content.
In these discussions I basically see people try to fool other experienced craftspeople about the reality and core axioms of the craft. The idea of ascending as a developer to a point where you don't need guardrails and never have to refactor code is just not going to convinced experienced developers. It's clear bullshit.
It's like trying to convince experienced motorcyclists that you don't need a helmet because you're quite the driver. It's just defensive driving, people! That the helmet is some sort of crutch you've transcended, and maybe if everyone had a bit more skill -- like yourself -- they'd understand.
Yet it always seems to be half of the dynamically- vs statically-typed language debate.
> Forgive me, but when I program I know what the variables I am working with are doing, and what kind of data they are storing.
That sounds fine, as long as no-one else will ever have to read or work on your code.
Including future you.
Do you work on small or large code bases? On truly large projects you often find yourself making changes without that level of deep understanding.
On these projects you often find yourself needing to work on higher levels of abstraction. Types help here by instantly telling you what the data is and providing hints.
Types take extra time to write and maintain, but they significantly reduce the difficulty of working on large projects.
> Forgive me, but when I program I know what the variables I am working with are doing, and what kind of data they are storing.
Can you say the same about all your dependencies?
Maybe you are one of those 10x programmers who can magically keep track of all the type data in your head and always catch yourself before you push to prod.
I and most people however are human and make mistakes sometimes. Worse, the bigger the project, the more you need to collaborate between people and sometimes teams. Types are almost like docs that check your code at compile time and reduce the chances of human error creating a production failure. Its not a panacea but its certainly nice to know that if I change a functions parameter, that the system breaks someone else's code depends on that function following a certain signature. At that point, I can either write a different function, message him to update his code or discuss how to make the changes together. All 3 cases are MASSIVE upgrades over fiding out shit broke in prod with some undefined behavior arising.
The line of perfect and infallible humans began with you, and will one day end with you. The rest of us need a bit of help to smooth over our human faults.
The only perfect decision I made is to accept that I make imperfect decisions, I wish I could attain the consistent perfection that you describe here.
I've developed with JS, PHP, and Ruby for about 5 years. Then I switch to statically type languages for the next 5 years (Scala then to Typescript). If I had to choose, I would choose static typing.
For small projects, dynamically typed languages are fine. but as the project grows bigger, the static typing will help and will make thing simpler.
As the project grows, refactoring will be an issue. Static typing will make it simpler to refactor.
Tests are smaller.
Reading the code will be easier since you know the contract of functions.
Fewer runtime errors since most errors will be caught at compile time. Also, the stronger the type system it is, the more it will be caught at compile time.
I don't think it slows me down that much. It's a little more typing, and there is compile time overhead. In some cases, you have to work your way around the type system. But at least with Scala, I am confident my code will work as intended as long as it compiles successfully. I spend less time debugging in runtime and writing tests. I think static typing might save time in the long run but not short run.
Hey, I've also made the trip from Scala to Typescript. We're talking ZIO and Shapeless wrangling. Twitter vs Scala futures. All that fun stuff (and I loved scala nonetheless).
Would love to know how your journey was. At first I was super hesitant, but now I am actually floored at the power Typescript has. The ability to tell the compiler to simply "trust me" has enabled me to build many abstractions I'd battle for hours to do in Scala.
I haven't played with ZIO that much. I do like it though. It seems to make your Scala code much more functional.
I'm 100% TypeScript now and miss Scala. I miss using monads. But since Typescript doesn't have for comprehensions, using any of the monad libs for TS (like fp-ts) is messier than plain old TS. Also, Typescript doesn't have pattern matching, thus ADTs are more painful in TS.
But TS is a nice language. Instead of monads, they have stuff built into the language to make things easier and cleaner like null coalescing (compared to Option) and async/await (compared to using IO or Future). I can live with that. I've grown to like TS.
I'm curious what abstractions you had easier time with in TS compared to Scala.
A lot may have been simply my own inexpertise in Scala. But I remember it being much more of a fight, and subject to much more nuanced errors, to do anything interesting with generics or any more advanced typing. I would often stop, whereas at the same point in Typescript, I can just cast, and then see what actually happens at runtime. If I fail to be creative enough with my types, so long as I satisfy the type contract at some level, I can be wild wild west in the internals.
I do miss the for comprehensions, but have built an abstraction that does the same thing for my purposes. It isn't quite as good, due to the whole monad thing, and me fitting it to the average Javascript programmer who won't want to learn functional programming all at once. So at its core it is pretty much async/await with sugar.
I quite enjoy exploiting structural typing for unit testing purposes. Gone is the need to learn a mock framework and its DSL; just write plain ol' JS for the parts you are interested in, and tell the compiler to chill. ;) Long term, of course, you should probably just have doubles.
Hey, same situation! As the resident rabid FP evangelist at work, people are often surprised by how much I like like TypeScript.
Personally, I think structural typing systems are the path forward for functional languages, and that means accepting that Haskell needs to go to move on to a retirement home. I was pleasantly surprised by how well Scala did subtyping with ZIO's `Has` + variance annotations. Shame TypeScript is bivariant with function parameters.
I agree so hard
I've been programming for 40 years and I agree. Strong typing has a religious quality. You have to believe that most errors are caused by type mismatch, and I simply don't believe that. Most errors, in my experience, are caused by bad architecture, poor documentation, and poor communications strategies between MVC, etc.
I have a little less experience, only 30 years, but I have to fully agree with you. Not sure why you got down voted (maybe the religious popularity crowd rearing its head).
I have seen my share of "innovations" come and go, but I too fail to see the empirical evidence that most bugs/errors are caused by type mismatch. In fact, I would even go as far as to argue that in my experience the benefits of typed languages (and the class of bugs they prevent) do not outweigh the usually larger code size (and often even additional complexity).
Maybe I've just tried the wrong languages, but I was never convinced of the great improvements usually promised. At the same time, I have seen other people twist and jump through hoops, while vigorously holding on to their conviction how all that is an improvement.
Sure, some errors will move from run time to compile time with typed languages. But if those are a systemic problem in your code, you probably have even bigger things to worry about (the ones you already keenly pointed out).
From a cynical point of view, I can understand why corporate entities would love typed languages (for the increased code size and complexity), but that's another story.
> Not sure why you got down voted
For the (pretty obvious) logical error of claiming that you have to believe that most errors are caused by type mismatch to consider stating typing beneficial.
I have 15 years of development experience (including a lot of spare time spent on open source projects) and I also agree word-for-word.
I like typescript not because it prevents most errors in my code, but because it prevents some errors. Those errors, in my experience, tend to be ones that are time consuming to identify and solve.
A value of the wrong type passed forward because it's almost the right type can cause errors that make their way into production.
I hear you say "so unit test your code!", and to that I reply, we're a c# shop that has only recently started pushing some of our code to the client. If you can convince management that we should shift our paradigm to allow for the time to write tests that don't add much to the sprint we're in, I can send you their email address.
The fact is, a large portion of unit tests solve the same problems that strong types solve.
I've spent more time helping people hunt down "undefined is not a function" and "Cannot read property of undefined" than just about anything else. Two observations from this:
1.) The fact that I even got involved meant the issues were particularly hard to track down
2.) These errors seem to be more of a time sync within a larger team/project than many realize
Typically these were caused by either scope issues and/or some context object that's been riding dirty all day. In the case of the latter hunting down the code that did the naughty can be particularly soul crushing.
It's not about most errors being due to type mismatch, as much as it is about being able to model your domain.
By having types, you open the door to formally describing the building blocks of your system. This lets you create very specific, well understood, pure pieces that then are composed together to bring about your desired functionality.
Why rely on documentation that a compiler cannot statically verify, as opposed to a type (annotation or otherwise) that can?
I think you're correct regarding your "most errors are caused by" comment, and no programming paradigm will ever get rid of these - you can always find a way to write bad code. And you are also correct that there are type zealots out there who create beautiful prisons they call abstractions. But at the end of the day, types are a tool, and while I'd highly recommend learning them, I also recognize some projects and teams will never make use of them.
Why is it one or the other? Type errors also certainly occur.
If you eliminate a class of errors by doing so, isn't that still less errors overall?
> poor documentation
Static types are documentation. Better yet they're documentation that can't go stale without a computer yelling at you that it's wrong.
> > poor documentation
> Static types are documentation. Better yet they're documentation that can't go stale without a computer yelling at you that it's wrong.
Absolutely, and I'd go further:
"Most errors, in my experience, are caused by bad architecture, poor documentation, and poor communications strategies between MVC, etc"
Good static types (a la Hindley-Milner) encourage good architecture, serve is documentation that cannot go stale, and encourage good communication strategies between different parts of a codebase.
The thing I have found the most useful with typescript is that it punishes you for doing the kind of cutesy stuff that permeated the node ecosystem in the early days.
"Pass in three parameters with a callback in the fourth position. The second param is configuration so pass in a string, but if you need to really customize stuff actually pass in an object instead and by the way if you don't have a third parameter then just chuck the callback there, why not!?"
Typescript is great in that somehow it is technically possible to write types for existing code written like this, but writing new code like that is cumbersome enough to prevent it.
Yes! My pet peeve with public APIs are DTOs that are like this!
"This is an array of strings, but it could be an object. If it's an object it will have this key and based on the name of the key it's this type. But it could also have or not have this other key and..."
ARghhhh! You can tell what kinda language the back-end was written in with that crap because while TypeScript can actually type most of that stuff it's a huge mess in something like C#, Golang, Java, etc.
Actually, you can "type" that call. But I always found the "giant ball if config" style painful. For example, I believe it was done data table library that took over a page of config options to get set up.
The problem is, you'd have to have the documentation open to make the slightest tweak to anything. No help from the type system.
"That's just like, your opinion, man." So sick of opinion in this industry. We should not accept such lazy arguments anymore. If you want to make an assertion, back it up. I will make my argument for why types are a good thing below:
I don't agree with you. I don't think that loose typing is based on opinion, and I do not think it is because people who start out in statically typed languages are unable to "grasp" loose typing. I think we are seeing a people abandon loose typing because the industry has observed that loose typing is harmful to even small, a few thousand lines, projects.
Static typing catches bugs. It makes your code easier to maintain. It makes your code safer to refactor. It checks your code to ensure correctness. It provides documentation about variables. It reduces the amount of code you have to read in order to understand a specific piece of code. These are empirically good things that you do not get in loosely typed languages.
An untyped value does not carry any information or explicit assertions about the variable. Take a URL for example: A "string" URL does not carry any information about weather or not the url string is a valid URL.
In an untyped environment, only by understanding ALL upstream code are we able to make assumptions about downstream code. We know that the "string URL" is a sequence of characters, and nothing more.
However, if we have a type, we can have a "URL" type. Since we have a type, we do not need to concern ourselves with all upstream code, only the code associated with the "URL" type. So, instead of potentially thousands of places to seek information about our "URL" variable, we have only one: The "URL" type. We look at the implementation of that type, and we know weather or not the URL has been validated.
Types dramatically reduce the amount of code you have to read in order to understand a given piece of your application. This makes your application more secure, more readable, and easier to maintain.
> "That's just like, your opinion, man." So sick of opinion in this industry. We should not accept such lazy arguments anymore.
Oh, wow, given this unnecessarily combative start, am I about to finally read conclusive proof that will stop that over sixty years old flamewar?
> I think we are seeing a people abandon loose typing because the industry has observed that loose typing is harmful to even small, a few thousand lines, projects.
People are not abandoning or adopting anything, both static and dynamic typing have existed for as long as computers have been a thing. Hell, LISP is older than pretty much every statically typed language still widely used, methinks.
> Static typing catches bugs. It makes your code easier to maintain. It makes your code safer to refactor. It checks your code to ensure correctness. It provides documentation about variables. It reduces the amount of code you have to read in order to understand a specific piece of code. These are empirically good things that you do not get in loosely typed languages.
Where's this empiric evidence of all these advantages you mention? I'm a bit shocked that I managed to miss it... And that so did half the industry. Such conclusive study would have ended that and the industry would have coalesced into this unquestionably superior type system you mention.
> An untyped value does not carry any information or explicit assertions about the variable. Take a URL for example: A "string" URL does not carry any information about weather or not the url string is a valid URL.
Can't do that with static languages either. Call it a type (or class), call it a parsing function, ultimately the result is the same. You need something to ensure that it is an url. Those exist in dynamically typed languages and are not obviated in static ones.
> Types dramatically reduce the amount of code you have to read in order to understand a given piece of your application.
Conversely, types substantially increase the amount of overall code one has to write.
These has never been a matter of opinions. The flamewar still rages after decades because what's the factually best type system hasn't been found. Hell, we might be likely closer to prove that that question has no answer.
In short, ultimately everything you said was just, like, your opinion, man.
> Can't do that with static languages either. Call it a type (or class), call it a parsing function, ultimately the result is the same. You need something to ensure that it is an url. Those exist in dynamically typed languages and are not obviated in static ones.
In a loosely typed language you cannot have compiler-level enforcement that a variable has been produced by a factory function that ensures that the passed in variable has been parsed and determined valid.
Additionally in a loosely typed language you do not even get the OPTION of labeling a value as "validated/unvalidated", you only have one option: Pass a string, and expect the new developer to read upstream code to understand where the variable came from.
> In short, ultimately everything you said was just, like, your opinion, man.
Is it my opinion though? Or did I pull it straight out of Building Secure and Reliably Systems, a book written by Google engineers to express industry best practice for developing software at a scale?
My previous comment was merely an attempt to mention how participating in this flamewar leads nowhere. I'm certainly not about to get into it by discussing details of the good and the bad and even the necessity of compile time checks of whether a string is a url.
Hundreds of books have been written on the matter, and the results are still inconclusive.
> Is it my opinion though? Or did I pull it straight out of Building Secure and Reliably Systems, a book written by Google engineers to express industry best practice for developing software at a scale?
Yes and yes, you happen to share their opinion.
Now, should we pretend that appeals to authority turn an opinion into fact now? If so, to whose authority should we appeal? Theirs? The different google engineers who work in more dynamic languages? Hell, designers of dynamic languages who have worked at Google? The people who designed and work in LISP or any of its derivates? Whose authority weighs more?
Or maybe we should acknowledge that appeals to authority hold no real decisive value in deciding something like this, and instead contribute to studies trying to gauge how effective different type systems actually are.
Except that even those turn into flamewars: https://www.hillelwayne.com/post/this-is-how-science-happens...
What do you think about this study that compared task completion in java and groovy from which I will paste the conclusion.
> Conclusion This paper described an experiment comparing static and dy- namic type systems for programming tasks in an undocu- mented API. We gave 27 subjects five programming tasks and found that the type systems had a significant impact on the development time: for three of five tasks me measured a positive impact of the static type system, for two tasks we measured a positive impact of the dynamic type system. Based on the previous discussion, our overall conclusions for the use of static/dynamic type systems in undocumented APIs are the following: 1. There is no simple answer to the static vs. dynamic typing question: The question of whether or not static types are helpful for developers cannot be generally an- swered without taking the programming tasks into ac- count. In fact, this is completely consistent with the results of previous experiments, such as Prechelt and Tichy’s [22], or our own experiments[10, 28]. 2. The type system has an influence on the development time: The choice of the static or dynamic type system had an influence on the development time for all program- ming tasks in the experiment. Again, this is consistent with previous experiments (such as [11, 22, 28]). 3. Dynamic type systems potentially reduce develop- ment times for easier tasks: Although we are currently not aware of how to determine exactly what “easy” and “hard” means, it seems that if a dynamic type systems has a positive impact, it is for easier tasks (which is consistent with the experiments described in [10, 28]). Although there was one counter example in the experi- ment (task 1), we think that the result for this task is a consequence of the chosen subjects’ low familiarity with the dynamic language, Groovy (despite the presence of a warmup task). 4. Static type systems reduce development times if (a) the type annotations explicitely document design de- cisions, or (b) the number of classes to identify in the programming tasks is relatively high.
https://www.researchgate.net/publication/262317340_An_empiri...
Given the challenges to getting a good result identified in the study how do you think it could have been done better today?
Yup, that conclusion, specially number one, is pretty much a formal detailing of what I tried to say in my previous comment: Results inconclusive, depends on the task, etc.
And, of course there are exceptions in both directions for all of findings 2, 3 and 4; and those exceptions would also contribute to 1.
It's for findings like those that I wish people stopped treating type systems like religions. And paradigms, for that matter.
> TS feels like something that was created to lure programmers who couldn’t wrap their heads around JS loose nature. Almost like it was created to convince Java and C# developers to use JS.
This is true, and confirmed by the TypeScript team
https://stackoverflow.blog/2020/06/15/talking-typescript-wit...
> Do you remember why the team came up with TypeScript, why you wanted to release something like this?
> A: When I joined the team, there were a lot of people at Microsoft who wanted to develop JavaScript at what we call “application scale.” Teams like TFS and Office wanted to build large JavaScript applications. A lot of those people had familiarity with statically-typed languages— C++, C#, Java, that kind of thing. They wanted to have that static typing available both for conceptual scalability and for the tooling.
> The language experts at Microsoft looked at the situation and said, well, we could try to write a new language like people had done before. There are projects like Script#, which takes C sharp and turns it into JavaScript, or languages like CoffeeScript that said, what if JavaScript had a different syntax? But what they decided instead was to just take JavaScript and add static types on top of that.
> At the time, JavaScript was experiencing a renaissance of growth, where they were adding features to the language again for the first time in a pretty long time. People wanted to use those cool new features, like arrow functions and classes, and they didn’t want to wait for all browsers to adopt them. They wanted to be able to use those features right away. I think those were the three things that TypeScript offered upfront: static typing for error finding purposes, leveraging that static type information for tooling, and providing the JavaScript features of tomorrow, today.
> TS feels like something that was created to lure programmers who couldn’t wrap their heads around JS loose nature
Seriously?
> They wanted to have that static typing available both for conceptual scalability and for the tooling
Sounds like they understood the loose nature pretty darn well.
> TS feels like something that was created to lure programmers who couldn’t wrap their heads around JS loose nature.
TypeScript adds additional type checking at transpile time to code. The assumption that the people who can write code with these more rigorous checks can't write the same code with it all removed ... I would examine that a little more closely.
I'm not a huge fan of TS not because I don't appreciate types but because I don't feel like it gives me any real type safety. Not due to the language itself but because I have to connect whatever I write to something else, and I wind up writing the type checking myself.
It's the same BS as Python and JS, the lack of typing but fundamental nature of systems that require data to be typed means half my code is checking that everything is properly typed!
Dynamic types have their uses, but in general they're more trouble than just writing typed code to begin with. And when your type system is more a suggestion than anything it provides little benefits.
> TS feels like something that was created to lure programmers who couldn’t wrap their heads around JS loose nature. Almost like it was created to convince Java and C# developers to use JS.
On the contrary, as somebody who learned programming with a mix of static and dynamic types, I felt like TypeScript showed me what a good type system was capable of in giving me the best of both worlds.
Instead of being pedantry, I felt like the type system was actually on my side for once and helping me to write correct code with fewer unaccounted-for corner cases and unexpected runtime crashes. And it does that while avoiding the feeling I got from previous statically-typed languages I used where the type system felt like a straight jacket incapable of expressing non-trivial concepts and relationships.
Perhaps one reason why I feel like I do about it is that I write a lot of prototype code and maybe sub-consciously it makes me feel like I’m losing speed.
What you call "Javascript's loose nature" I call a minefield of behaviors and semantics that make writing correct Javascript code so incredibly challenging.
I use Typescript everywhere I need Javascript these days, it's a breath of fresh air, and my code feels maintainable, tractable, and much easier to refactor.
Thank you for the bold statement. I feel the same. I’m at home with Clojure, and Ruby. The same paradigms map well to JS. For the last 9 years, I have been a lecturer at the university of applied sciences in Zurich, Switzerland. In that time, I saw more and more students coming from Java and C# to JS.
They like TS a lot. And it’s obvious why. Having said that, I know no “old” programmer who used to prefer a different paradigm to express a wish to switch to TS.
Rich Hickey put it well in this quote “ Functional programs are desirable because they are simpler and easier to reason about, due to being mathematical i.e. they are free of time and place.”. I agree.
That quote is not really relevant: TS is as functional as JS.
Not really in the same way, though.
I mentioned that paradigms of functional programming languages like Clojure translate well to JavaScript. They do not to typescript, because it is a statically typed language.
If you are interested in why are you dynamically typed language has benefits for functional programming, please see this talk: https://youtu.be/oytL881p-nQ
Typescript typing is fundamentally optional, so this criticism, even if true regarding statically typed languages, does not apply to Typescript.
Typing is optional both for individual variables via the `any` type, and compiler-wide, by configuring it to assume untyped variables are `any` by default.
That talk is not about the benefits of dynamically typed languages over statically typed languages. Do you have a specific point in mind?
It's sad that you have to be worried about downvotes for an opinion.
I disagree, though. Instead of going with a lengthy list of why I think TS is great and disproving your arguments, which I assume everyone else will do, I'll admit that types can be hard, and so doing them right, or even doing them as best as one can, will always take some time. For a small project or a small team, that time might be hard to justify. But I think this is resolved with a good understanding TypeScript.
Even so, TypeScript might not make sense for many projects or small teams, but I find it hard to defend that TypeScript won't be a net win for any medium team or medium-size project.
This was my believe before, but I've seen multiple teams go from JS to Flow or TypeScript and the result has always been, when there's expert guidance, extremely positive. Productivity goes up, more bugs are fixed because there's more confidence in the safety of the changes, more people feel confident to work on any part of the codebase (vs just the people that originally built it or have worked more on it), and the defect rate dropped dramatically.
your viewpoint might change when you're working on a large project with lots of developers and your system goes down in production because of a type mismatch the compiler could have easily let you know about long before you deployed (i speak from experience).
All it takes is once and you'll become a statically typed language evangelist.
Are unit tests a regular habit of yours? If they are, you will remember the time you came to lean on them to make your programming faster. Sure, they are lot of work upfront, but the pay off when when you modify code with units tests later is you feel safer, you write code faster and looser, and yet providing the you keep the unit test habit up the quality is the same or even better.
People who use types regularly feel the same way about typed languages. Types don't test as many things of unit tests of course, but feedback you get on what they do test is immediate - literally as you type in a IDE. The speed of that feedback is important. It's a well know in quality circles that errors discovered later cost far more to repair. In the case of types in makes you don't write a hundred lines of code under the expectation a type provides method foo(), only do find out later the foo() provided takes an argument argument you don't happen to having lying around.
While payback for types over unit tests is smaller, the effort required to use types is at least commensurately smaller, and the amount of typing required is way smaller, particularly now we have type inference. Also in my experience unit test's need to reach every line of your code forces some pretty tight constraints on how you structure it. Who hasn't had to refactor some block of code so you could test some obscure corner case catering to an unexpected error? Types don't require that - the compiler always sees everything. None of this matters much if you are going to write unit tests anyway of course, but no one does that for small projects. This is another advantage of the type system - it's always there, even for 5 five liner.
Finally, types come with an added bonus. They give the compiler more information to work with, which means the compiler can make programs run faster. Rust talks about cost free abstractions, which the extreme case: the compiler knows so much about what you are doing it generates no code at all. In rusts case it rarely has to check for if a pointer references null before accessing, and greatly reduces the number of array bounds checks, has no garbage collector, and the pattern of a function checking the number and type or argument in order to implement overloads just disappears - along with the runtime overhead of doing the checking.
You don’t see the benefits of a strongly typed language?
Python is strongly typed, don't confuse static and strong typing.
You’re right.
I do. But not for JS in particular. At the end of the day 95% of JS that is written in classic JS and is used in thousands of high-scale projects like that.
I would say for me, typechecking part of ts is less useful than the information it provides me about the project. I can jump in a new project and quickly see what kind of data structures are there, what are the parameters, get really nice intellisense and documentation.
All of this is possible with jsdocs and flow but they are not nearly as powerful as ts and often times verbose. I don't like polluting the comments.
You don't need to use typescript everywhere although the popular zeitgeist will tell you to avoid any or ts-ignore. It's fine to write some parts in ts and others in js. Think of ts as eslint, jsdocs or flow. You don't need to be religious about it. Take its benefits wherever you can or do you think all the other tools are useless as well?
> who couldn’t wrap their heads around JS loose nature
Ultimately, for any serious work, especially enterprise level work, your team members may include people of different calibers.
In such a case, where you have to work with code written by other members of your team, it becomes a serious problem to develop quality code.
For lone developers, it should not be a problem. But in enterprise settings, I think that is the reason why Node is not popular.
+100 I'm on your team, 100% agree with your points, TS is a waste of time and I'm encouraging my team to drop it.
Static typing shows you to eliminate the class of tests I like to call “spelling mistakes tests”, something I grew to loathe in Puthon. You have a method called doSomething. You’d better make sure your code isn’t trying to call doSomethign.
Compile time errors are much quicker and cheaper to detect and fix than runtime errors.
The entire comment did not mention testing so it sounds like you never have to continue working on a codebase and eventually face the challenges of refactoring something that you didn't write or remember writing. How about self-documnted code how often do you work with others?
I do work with others in non-TS codebases. I think I just been conditioned to think like that. I’m a product of my environment. I know my opinion is biased and after reading many of these comments I understand why people get a lot of value from it. I mean, I have always known that. Otherwise it wouldn’t be as popular.
It just happens to be that I have never been exposed to the circumstances that would make me re-evalute TypeScript merits.
I've moved back and forth between statically typed and dynamically typed languages many times over a couple of decades and I've come to the exact same conclusion as you. People who are equally skilled with both paradigms will prefer dynamically typed languages; simply because there is almost no added value of having static types and in TypeScript's case it's not worth the extra transpilation step and all the problems that it creates.
Accidentally mixing incompatible types is mostly a problem for junior developers. I'm much more likely to accidentally put on my pants, socks and shoes in the reverse order in my daily life than mix up incompatible types in my code.
The solution is not to add stickers all over your clothes to remind you which way is the front or what order you need to put them on; you don't need more tools, you just need more focus.
Why such a large, important project would want to drop static types is beyond me.
> TypeScript isn’t proving itself helpful to organize Deno code. On the contrary, the Deno team is experiencing the opposite effect. One of the issues mentioned is that they ended up with duplicate independent Body classes in two locations
This feels like process immaturity or unfamiliarity. Thousands of other projects manage to do just fine.
These folks are free to do what they want with their project, but this is not a good look, especially to those that are skeptical of the javascript ecosystem.
Most of the project is and will still be written in Rust, a statically typed language, so saying that the "project" will drop static types is an overstatement. Based on the design document where the devs talk about this, the TS code in question is about 10k lines of glue code between Rust & userland JS/TS.
If it’s only 10k lines of glue code how are they running into minutes long compiles?
Presumably that's what the Deno team is wondering
Haven't looked at their build, but it's almost certainly the case that they are generating some sort of rust binding from the typescript code and the compilation times are actually from needing to recompile rust.
10K is a lot of code.
As a maintainer of a popular 3k LOC typescript library, even at 1k LOC you start running into frequent type-related bugs with JavaScript
Working on half a million LOC TypeScript codebase. All strict flags up, low-2-digit team size. We don't really run into many problems. TypeScript is not perfect, but developer happiness and productivity have definitely increased since we adopted it, and defect rates have dropped significantly --while increasing the size of the team & working on more features.
Think of the change as a statically compiled language writing parts of their runtime with assembly or unsafe pointers. It’s not an indictment of TypeScript.
My first impression of the reasons in the design doc is that the change is not well justified, but I also see the point you make; my response, though, was to the direct parent comment.
I have a hard time believing that. We have 10k lines of typescript and that take forever to compile compared to 5x more of the ReasonML code we have that compiles instantly
You have a hard time believing that their team experienced more happiness and productivity with TS...because your ReasonML code compiles a lot faster than your TS code?
I've actually been (very) wary of adopting TypeScript once I learned of the multi-second compile times, even for tiny projects.
I had actually been watching Deno in case they solved any of that.
They become really frustrating as the project grows in size. Personally, it becomes really difficult to maintain productivity. As compile times tick up, I start bouncing over to other tabs rather than just twiddling my thumbs starring at a terminal. Then I realize I've been on Reddit for a half-hour.
I recently watched this talk by Johnathan Blow[0] where he talks about quality of life in programming languages and spends a fair amount of time talking about compile times and their effects.
I think we collectively need to re-align on being performance focused. Tools are simultaneously amazing but crummy at the same time.
I don't love the compile times, but I'll also say with TypeScript I tend to check the browser that often. TS also means simpler refactoring, for example.
Note also: * type checks can run in parallel, so they won't block your other build block * the tsc has been making gradual improvements to performance and techniques to improve compilation and type checking * there are speedy alternatives to the TypeScript compiler (tsc) (eg: https://sucrase.io) for transpilation
Much faster compiles times sounds like a good reason to me ;)
I wasn't comparing to ReasonML, which I'm convinced is a very good choice.
I've worked on javascript codebases pushing half a million lines of code, and my memory is that we didn't run into type bugs all that often. The biggest downside was the lack of automated refactoring tools - this was many years ago now.
It did take quite a bit of discipline, but with a skilled team it really wasn't all that hard.
If your memory is good, I'm impressed.
> It did take quite a bit of discipline, but with a skilled team it really wasn't all that hard.
Out of curiosity, what was the turnover within the team? My personal experience is that static typing helps a lot when you're new to a codebase. Probably less so when everybody can recite the architecture in their sleep.
The turnover didn't start increasing until the 'javascript ecosystem' developed, and suddenly everyone wished that they were following the new community developed practices rather than the ones we'd be following for years. That lead to lots of factionalism within the team and a lot of unhappiness on all sides.
> The biggest downside was the lack of automated refactoring tools
That's what a typechecker gives you–an automated enforcement mechanism for ruling out certain errors during refactoring.
10k is a lot of code? No way that is a lot of code or at least it’s not a lot for senior devs.
This certainly depends on what the code does and on the use case, i.e. on how critical reliability and performance are. 10k code in a simple web application prototype that will be trashed in 3 months is not "a lot", because it's not critical and piling up technical dept is not a problem. 10k code to specify the core algorithms in a mission-critical, long-living system is "a lot", or at least "much more", because it needs to be crafted and maintained with immense care.
Unless one is paid in LOC I'd expect a senior dev to write less code than a novice...
It's enough to benefit from types, assuming no large swathes of inline literals.
As someone who has maintained multiple legacy projects, 10k is not a lot of code. I normally run into single files in the 10k range, if it wasn't for NP++ and VSCode I would go insane just trying to scroll.
No, it’s not. 10k loc is a small project.
If compilation times are a problem with typescript I do not see how Rust will help.
Maybe that means it is not as bad as it sounds, but if it's true it makes no sense to me. How could you possibly have minutes of compile time on so few lines of code? The typescript compiler isn't that slow.
I've witnessed teams that have switched from static typing to dynamic typing before, due to complaints about compile times and a lack of ability. It doesn't take long before their testkit balloons and they spend 10x the time on testing, dwarfing any savings they made by eliminating compilation. Or worse, the code turns into something magical but untouchable, lest something break...eliminating the ability that they imagined they would get.
Why is anyone in the world manually writing 10k lines of glue code? You don't need TS or JS, you need.. a computer.
Please, elaborate.
I would guess that he means that when you have a lot of glue code it tends to be repetitive and so writing tools to write the glue code can be a win. Let's say you have implemented a service that exposes API X to its users, and let's say you have an internal service that provides the actual functionality you are trying to expose but uses API Y. Hence you need glue code that translates between X and Y.
There might be hundreds of API calls in X but the glue code is all going to be of the same general form: translate the X parameters to corresponding Y parameters, call the matching Y function, and then translate results back.
Within all these glue functions there will be a lot of common actions. X calls with integer parameters for instance might pass them as ASCII strings and Y might expect integers as 64-bit big-endian binary.
In this situation there is a good chance you can make a table that lists each X call, the types of its arguments and results, the Y call to map it to, and some flags to indicate that some things need special handling and what those are.
You can then have a program, probably a fairly short and straightforward program, that reads that table and writes out the glue code for you, sticking in comments marking places where you need to edit it to deal with those places marked as needing special handling.
I suspect there might be more than one definition of "glue code" at play here.
Codegen?
Yeah, I tend to agree. After 18 months with TypeScript, I can't really imagine going away from it. After every single refactoring I do, I'm extremely grateful for proper typing. Not to mention sugar like null coalescing, etc.
null coalescing is good, but I personally found that Typescript doesn't offer many advantages on a large team. I know it's not cool these days! But it just slows me down and if you're reasoning about functions I never run into that many production level issues with types, but maybe that's just my brain I dunno!
What is it about a large team that causes it to stop offering an advantage? If anything I’d expect it to be more useful as a code base grows in complexity
Agreed, as the team gets larger and an given individual doesn’t necessarily know how everything works from memory the need to rely on the compiler and type safety should grow.
I guess it tends to be superseded by other forms of rot, people writing a bunch of tests that aren't against the critical path, money going down the drain... I agree, it _seems_ like what you say is true. I'm not a computer scientist, I'm just saying I've tried TS at a couple of shops, and as they team grows TS slows us down. Maybe it's just stochastic or random, but at the end of the day there's no academic "proof" types improve developer productivity. The only thing that sort of gets me is how everyone sort of assumes TS is 'best practice' but there's really no evidence besides gut feeling. My gut feeling is now telling me TS is not beneficial... I'd love to play devils advocate against my own position so feel free to tear me apart...
I consistently find types just so useful I don't know how anyone works without them.
Things like when this system was built all the code assumed social security could not be null. We now need to make the system able to handle a null social security system. What code do I change?
Do I need to null check the results of this value?
What does this function return and how can I be sure I'm handling all use cases?
Lisp is large, important, and also not statically typed. It's worked out ok for Lisp programmers. JS itself isn't strongly typed and is the most successful and important language in the world (probably in the history of programming), so that's two game-changers that don't require static typing.
JavaScript is the most popular language solely because it's the only one that runs in webbrowsers natively. The language itself is not good, it's rather bad from a language designer's point of view.
Lisp is not popular.
Remove the browser practical monopoly, and JS popularity would vanish.
Browser monopoly led lots of devs to learn JS, then NodeJS showed that lots of devs want to keep using JS. It's actually possible for people to like it.
Also, languages are always a function of their ecosystems. You could argue, remove Apple products and Swift/ObjC would vanish.
Nodejs showed that a lot of developers are lazy and want 1 language to learn
Not developers; businesses. What do you think a business would prefer: hiring cheap ubiquitous JS devs and using them interchangeably for frontend and backend work, or hiring/training devs separately for backend stacks like Java?
Certainly you didn't go through the entire pro con list of Node over other languages and go "it must be developer laziness!"
Easy to reason about, great performance for most cases, simple to debug and write code for, a plethora of libraries, easy to ship, no need to have different teams for backend/frontend, and minimal tooling needed.
The only really unique thing JS is bringing to the table is that it also has a privileged position in the front end. Your list of benefits it provides boils down to stuff multiple large languages all have, and the one thing that means you can learn just JS.
GP comment was presented somewhat snarkily, but I'm not sure they're all that wrong.
Yikes to see people assume so little about others. Why not ask people why they use Node instead of assuming the worst about them?
You don't think JS is obviously unique for its ubiquitous Promise, async/await, + async-everything abstraction. You tend to only get that in other languages (Rust, Python, Ruby) by limiting yourself to a fraction of the ecosystem.
Btw, what's lazy is making convenient uncharitable assumptions about others than just... asking.
This forum is full of people who could tell you why they still use JS after they analyze pros/cons of other languages.
I'm not entirely sure what you think I was saying. You refer to me assuming and being uncharitable in those assumptions, but I was responding to a specific list of items pointed out, and my own experience. I think you're actually assuming quite a bit about my comment.
> You don't think JS is obviously unique for its ubiquitous Promise, async/await, + async-everything abstraction. You tend to only get that in other languages (Rust, Python, Ruby) by limiting yourself to a fraction of the ecosystem.
A fraction like nodejs or whatever subset of NPM you decide to use?
Core JS is what you get in a browser. That includes async/await, but it's hardly ubiquitous in usage in the core.
The main distinction JS has over Perl, Python, Ruby etc is that it's in the browser, so you can assume almost everyone has it and it's accessible in some manner if they access a web property you are responsible for.
I believe people here don't belong to the situation I mentioned.
You are here because you are interested and want to learn. You probably know more than 1 language.
But that is not the general developer. Most developers are lazy and at the end of the day, want to go back to their wife and kids ( for example).
Yeah, and there's absolutely nothing wrong with that. It's the sign of a healthy work-life balance.
The real problem is that businesses don't want to train devs in the right tools for the jobs at hand, and are instead looking for the shortcut that will let them 'ship it'.
> Yeah, and there's absolutely nothing wrong with that. It's the sign of a healthy work-life balance.
I agree, never claimed otherwise.
Sure other languages have some pieces of the puzzle - python has tons of libraries and is easy to understand, golang has great performance and is easy to write, etc.
But I have yet to find a language that has the same set of features except JS. If you want to offer up an alternative, please do so.
JS has zero unique set of feature.
There is not a single feature in JS you can't find elsewhere, often better implemented.
If anything, the vast majority of scripting languages (Python, Ruby, PHP...) have more features than JS.
JS is so lacking in features that half of its ecosystem is dedicated to compensate for that (typescript, babel, webpack, undersacore...).
Sure and julia has the best matrices, python has the most flexible threading models, erlang has the best distributed runtime..
Yet one feature does not a language make. A language is the whole of it's behavior, and JS is a perfectly fine solution with a wide mix of good features.
Is it the fastest? No. The most performant? Not close. Does it have the best ability to write language parsers? No!
But it's not supposed to. It's a general purpose language that's well suited for a wide swath of cases.
Most languages have transpilers and utility libraries - and those are useful tools but also not meant to be part of a language. Even python has dozens of compilation tools depending on how you intend to distribute your code.
It's the mark of a poor intelligence that buys on pros only without considering cons. We must weigh not only our features but how well the average engineer can use it, how quickly we can produce features and how safe our code is, and how easily we can actually hire and train engineers.
JS is one of the most popular languages in the world. My 10 year old nephew can write it and do a decent job of it.
You're missing the point here, which is not that each of these languages has something JS does, it's that Perl, Python, Ruby etc all support all the same features, have large ecosystems of modules, are easy to use, etc.
JS is a fine language. It doesn't really bring anything new/different to the table (other than prototype inheritance, but that doesn't amount to much IMO), so the real differentiating factor is that it has a privileged position because of browsers.
JS has a great future: first class ubiquitous promise + async-everything. Can't find that in Ruby/Python/PHP, you have to use something like Twisted/asyncio which limits you to a bolted on subset of the ecosystem, unlike in JS.
Very dishonest take btw.
Here's a forum of people who could tell you why they use JS instead of your $favelang, yet instead of trying to figure it out, you just assume everyone is lazy or a junior dev except for you.
You should be a little more suspicious of convenient little truths like that where you're the cool elite engineer protagonist and everyone else is a bumbling idiot.
I use JS on the server. Any questions for me?
Go and Erlang (or Elixir) both have a better async model, and are pretty much better designed on all points.
So for the rare cases where async does matter (and they are a niche, given even big names like facebook code behind async proxy and do long polling), there are still little reason to choose JS.
I can't think of a single mission where, if I were not being forced to use it, I would chose it over something else. And I say that while coding a LOT of JS all year long. Even training people regularly in the language.
I double down on my initial statement, if tomorrow JS is removed from the browser, it would die in a few years.
It's a badly designed language that has been accumulated fixes over the years to make it acceptable while never removing what's bad. It was so initially bad that half the ecosystem of JS exists to not code in JS (typescript, coffeescript, babel, jsx, webpack...).
And it has received that much of attention because we had no choice. Google spent millions to make a technical marvel of a JIT to run it at decent speed.
Any tech that would have had half the resources poured into it would today be the incarnation of skynet.
It's a language surviving on artificial life support than can do so because it has the best blackmail game of all time.
>Any tech that would have had half the resources poured into it would today be the incarnation of skynet.
Java?
Good example.
The JVM is one of the most amazing piece of tech ever created. It's so good it supports not only what has been most the popular language in the world for years, but many newly popular languages like Kotlin or Closure. The perf have been optimized so much they are getting about 70% of C/C++, but with high level paradigms. It can pretty much do everything.
In fact, it runs on everything. It used to run on old school nokia phones. It runs on some credit cards! Despite being slowed down by patent trolling, Java found its way to more than half the modern mobile phones in the world throught Dalvik reimplementation.
It's everywhere.
Today, it is still ranking #2 on TIOBE and PYPL, despite having to leave with 2 decades of legacy design decisions and no monopoly.
No, I'm experienced with node and other programming languages. I never said NodeJS is a bad language, that is not related to the statement i made.
I also didn't say everyone is lazy. I said a lot of developers.
Most people here do not belong to that use-case. As they are mostly here by interest and are willing to learn.
But most people, after work, don't do anything with their knowledge.
And are more willing to learn node as it's the same on the backend + frontend.
Or keep using what they already know, with no interest for other languages.
> Easy to reason about,
I'd like to know what language you use as a baseline for this?
I made my first "real" Javascript code back in 2005 (a vector map system that worked in realtime) and I've been working mostly with frontend for the last 3 years so it is not lack of familiarity. In between that however I have programmed a lot of other languages, worked in a number of different teams, written new code, maintained old code and generally gotten some perspective on life.
That perspective has sent Javascript down my list of languages that are easy to reason about.
Event threading pulls out a huge amount of difficulty with semaphores, locks, thread safety, etc.
The lack of OO means no typecasting, inheritance models, interfaces, etc.
Arrays are fully dynamic, not type restricted and operate strictly by reference.
No memory mapping, manual garbage collection or even GC adjustments.
Suddenly the list of things someone has to understand to be a competent JS engineer is way smaller than a language like C or Java.
There are other languages that have a similar level of being easy to understand such as Python and Ruby, and they're good languages too but have a different set of tradeoffs.
Have my upvote for the serious answer. Let's just say we have different opinions.
Here's my attempt to create something similar from my perspective:
- Being able to know to at any point what a variable can contain is very liberating. (Ok, you can define a list of Object that behaves just like a list in JS: "fully dynamic, not type restricted", but thankfully for people like me that is not common in Java anymore.)
- Knowing that the compiler has my back allows me to work faster.
- My preferred languages (Java, C#, TypeScript) together with version control allows me to refactor fearlessly.
It's a tradeoff. Dynamic isn't "better" than typesafety, but it's generally easier to comprehend and reason about. Just yesterday, I was working on a C# script and encountered the following problem:
+ An engineer had written a script with a Dictionary of type <Transform, Material>. If you've touched Unity, you immediately caught the flaw: Transform's aren't unique enough keys and it's really easy to end up trying to add Duplicate keys, even though you really mean different objects.
+ So, since we don't care about uniqueness, shift from a Dictionary to a List. Except we have a problem, because we need to keep that Key->Value relation so we know what transforms get what materials. Well, we have a solution to that, it's yet-another-type called a KeyValuePair.
+ Well we're now nesting a generic KeyValuePair that needs type information inside of a list that is holding <KeyValuePair> objects, which also changes how we iterate through that list and add items to it.
+ In a language like JS, everything I just said doesn't matter at all because instead of using a Dictionary (Map in JS), we would of just said "Use a Set instead". Done.
> It's actually possible for people to like it.
If they started using PHP, without monopoly, they would not have switched to JS.
But plenty of people have switched from PHP to python or ruby.
> Also, languages are always a function of their ecosystems. You could argue, remove Apple products and Swift/ObjC would vanish.
Python, C and Java are not.
I disagree on the current sentiment but agree that browser monopoly pushed js on people. If js didn't evolve over the last few years (since es5), I would have believed removing it from the browser would kill it.
Right now, you have options to avoid writing js at all. There might be some glue code in js but you can write vast majority of your code in other languages and target js. People still choose to write in js.
Purescript, elm, clojurescript, kotlin, bucklescript, and the list goes on. There is a to-js transpiler for every popular language. Why aren't they seeing more usage?
> Purescript, elm, clojurescript, kotlin, bucklescript, and the list goes on. There is a to-js transpiler for every popular language. Why aren't they seeing more usage?
Because a layer of indirection is a heavy price to pay.
If I could code in Python with zero cost in the browser, I would. Hell, I would code in Lua, Lisp or Ruby if that was the alternative.
Because for ecosystem and tooling JavaScript is the first class citizen. TypeScript was accepted as the defacto static typing system because it diverges so little, and valid JS is valid TS meaning example code can still be used close to verbatim.
tbh JS is popular only because of browser monopoly. JS became popular because of internet usage otherwise it would just die. It started with 1997 changed little at 1998 and 4th edition was even abandoned lol. and it took so long to evolve after that. in 2019 there was update and from 2015 we are seeing good progress. no we still cannot avoid because browser needs it. Hopefully wasm can replace but it still has long way to go.
So i don't subscribe to idea that js is not popular because of browser monopoly.
I am not disagreeing with that?
there's plenty of huge software projects in dynamically typed languages.
There are also huge classes of bugs that exist in these projects that a statically typed language completely eliminates!
If they're running into trouble from having to have types, it's almost certainly design and architecture issue and does not make me think that deno is going to be a solid project.
For dynamically typed languages, the idea is you make up for that class of bugs by incorporating TDD and having lots and lots of unit tests.
So, instead of waiting a minute for the typescript compiler, you wait for the engineer to write tests.
If youre doing tdd or writing tests like this you have bigger problems.
Type safety is easy in a dynamic language. Stop mutating variables and stop mixing types. Suddenly that whole class of errors evaporates. No need to test things that are impossible.
And for those times you want some magic in your life, nothing is stopping you, no need for generics, just proceed with caution and test accordingly.
and you wait a minute for the tests to run every time you commit a change
You could arrange to have a program write those tests for you based on your description of the project's data model. Oh wait...
You know what, that would already be better than most type systems.
Firstly, they'd be written in the same language that you are coding in, not a weird, half baked type language, that adds visual noise to your code.
Secondly, they'd have much more power to define meaningful and useful behaviour rather than being restricted to talk about correct behaviour via types.
Thirdly, they'd run when you wanted the tests to run, and you could tier different tests to run at different times, so they aren't all slowing you down while you're doing fast iteration.
I used to like types, but then I realised that what matters is how quickly you see the bug. Seeing it in your code editor is brilliant, but if it's slower in time than hitting control S and seeing the actual app in the other pane auto reload, and fail or not, then it's worse.
These days I look on the idea that you know the exact types of all data your program will interact with at the time you write your code as the same sort of mistake that we made when we thought we understood the deep inheritance hierarchies of the real world.
That's an interesting take. To some degree, I think I agreeing with you.
I write a lot of Purescript and a lot of Clojure. Purescript, being basically a Haskell variant, is about closing down every last little part of the system into types. You _do_ pick up a lot of visual noise for this (like `liftEffect` ugh...). Whereas Clojure, is the polar opposite. It's about keeping the system open, using large chunks of data, and having functions take/change what they need and pass along everything else none-the-wiser to what's present.
Bouncing back and forth between these two worlds, I think I've begun to lean towards the opinion that I really only care about strict types at the boundaries of my program and certain very specific checkpoints along the way (generally, something like a module/namespace boundary).
Clojure has Spec, but it misses the mark in my opinion because it doesn't solve refactoring. It's not (currently) instrumented enough to help the me as a human make changes to the code without also just "bumping into the guard rails" to try and figure out what I broke along the way.
A middle ground orthogonal type system sounds really appealing to me. "Type coverage" is an idea I've been kicking around. Something like Spec in Clojure, but more symbiotic with the host code such that it can tell you things _about_ your code and help in refactoring, symbol resolution, etc..
That's a lot of words, but tl;dr I think I agree with you : )
Thanks for treating my comment charitably, and for adding your experience. Type systems often seem to bring out the extremist in otherwise reasonable developers.
It's quite obvious that there are downsides to types that most developers are missing - because most developers seem to feel that they get massive benefit from types, but empirical studies seem to show that if there really are benefits, they are not massive.
I see the downsides in a few ways - they open up another avenue for 'architecture astronauting', they are not in fact accurate representations of the real world in many situations - you're dealing with files, or messages coming in from the network which are not typed, and even when they are (e.g. databases), they can change under your code while you're running. That's not to mention the points I made above around usually being an entirely different, hobbled language that gets sprinkled through your source code. Types encourage people to build ridiculous code generation pipelines during build time, and builds getting larger and flakier are about the worst thing in the world for fast iteration. I find the Smalltalk approach of coding in a live image really interesting, and I worry that obsession with types are closing off that kind of future. There's also the fact that your language, and particularly your type system constrains what code you write - like a programming version of Sapir Whorf, and most type systems are bad at expressing very high levels of abstraction. Scala had to invent a documentation tool that hid the real types of things because the type signature of higher order functions like map and reduce were scaring people.
I was interested in your opinion of Spec, because I'm aware of it and find it interesting, but I don't do a lot of Clojure so I haven't really used it practically. I liked that it aimed to address more than just verification - schemas, object generation for property testing, these things are all closely related to the general concept.
I think your ideas about a middle ground type system seem very interesting.
I saw recently that there's a version of Nim 'DrNim' that incorporates the Z3 theorem prover which allows you to assert and prove much more interesting things than typical type systems. It sounds fascinating.
If your application has any structure at all, you can often just run the tests for the part you're changing while you're working and committing locally. Once you're ready to push it you should probably run all the tests first even if your language has static types.
> you wait for the engineer to write tests
Which, if we're doing TDD, involves no waiting at all, since it was already written before the implementation. Ideally anyway.
I didn't read that types were causing problems. My understanding was TS, itself, was causing problems. Specifically waiting around for it to compile.
Strong typing is from OOPS, itself an optional programming methodology. There are many JS programs that simply access other (JSON) objects directly without going through an interface. In these instances, typing is counterproductive.
One of the beautiful things about JS (and Lisp) is that variables and functions are interchangeable and, the case of JS, both can be accessed directly without worrying about an interface.
Just use Typescript static types where it is useful. If you access a bunch of JSON objects and you don’t need the typing, you can always declare as ‘any’ and move on.
At the end of the day those type exist in JavaScript. If you access ‘first_name’ instead of ‘firstname’ it will not work. The difference is that typescript would let you know before running the code instead of getting an obscure runtime error.
Deno is having problems with TypeScript, but TypeScript is not the cause of that problem. The problem is a self inflicted issue of a name collision of their choosing.
Slow compile times are very much a problem caused by TypeScript.
You can do any manner of stupid things to make any compiler of any language to behave slowly, but that doesn’t mean all compilers are slow. If you want better output don’t deliver garbage for input.
My 3 year old laptop has no problems with TypeScript (neither Angular nor React), and I am a rather impatient guy when it comes to computers.
I'm honestly wondering: What are people doing to end up in a position where TypeScript compile times are a problem?
It is something to do with a class in their code named something similar to header conflicting with a same named definition in their index.d.ts file that is closely related to that class instance.
If they dropped use of classes, or differentiated the names of the two things in collision the problem would appear to be solved.
To turn that around and blame TypeScript as the point of failure is an extremely bad omen suggesting their code style opinions are more important than product delivery. I could live with that nonsense if this were a framework or some minor dependency, which this application is not.
My compile time went from seconds to minutes when I made a recursive immutable type (which I reverted of course). Overall, I still love typescript.
Edit for the curious, here's the monster type that caused such pathological build times...
type ImmutablePrimitive = undefined | null | boolean | string | number | Function; export type Immutable<T> = T extends ImmutablePrimitive ? T : T extends [infer U] ? readonly [Immutable<U>] : T extends [infer U, infer V] ? readonly [Immutable<U>, Immutable<V>] : T extends [infer U, infer V, infer X] ? readonly [Immutable<U>, Immutable<V>, Immutable<X>] : T extends [infer U, infer V, infer X, infer Y] ? readonly [Immutable<U>, Immutable<V>, Immutable<X>, Immutable<Y>] : T extends [infer U, infer V, infer X, infer Y, infer Z] ? readonly [Immutable<U>, Immutable<V>, Immutable<X>, Immutable<Y>, Immutable<Z>] : T extends readonly [infer U] ? readonly [Immutable<U>] : T extends readonly [infer U, infer V] ? readonly [Immutable<U>, Immutable<V>] : T extends readonly [infer U, infer V, infer X] ? readonly [Immutable<U>, Immutable<V>, Immutable<X>] : T extends readonly [infer U, infer V, infer X, infer Y] ? readonly [Immutable<U>, Immutable<V>, Immutable<X>, Immutable<Y>] : T extends readonly [infer U, infer V, infer X, infer Y, infer Z] ? readonly [Immutable<U>, Immutable<V>, Immutable<X>, Immutable<Y>, Immutable<Z>] : T extends Array<infer U> ? ImmutableArray<U> : T extends ReadonlyArray<infer U> ? ImmutableArray<U> : T extends Map<infer K, infer V> ? ImmutableMap<K, V> : T extends ReadonlyMap<infer K, infer V> ? ImmutableMap<K, V> : T extends Set<infer M> ? ImmutableSet<M> : T extends ReadonlySet<infer M> ? ImmutableSet<M> : ImmutableObject<T>; type ImmutableArray<T> = ReadonlyArray<Immutable<T>>; type ImmutableMap<K, V> = ReadonlyMap<Immutable<K>, Immutable<V>>; type ImmutableSet<T> = ReadonlySet<Immutable<T>>; type ImmutableObject<T> = { readonly [K in keyof T]: Immutable<T[K]> };
No, it’s not counterproductive to access JSON objects using a predefined schema, it saves your ass in case of typos.
> Lisp is large, important, and also not statically typed. It's worked out ok for Lisp programmers.
Lisp programmers use check-type[1] a lot, they proclaim[2] types for performance optimizations and they often deftype[3] if not only for code clarity. And then we have CLOS and its dispatching on types/classes...
[1] http://www.lispworks.com/documentation/HyperSpec/Body/m_chec... [2] http://www.lispworks.com/documentation/HyperSpec/Body/f_proc... [3] http://www.lispworks.com/documentation/HyperSpec/Body/m_deft...
Lisp is important for its intellectual contributions, not for its use in large production systems.
It's used for every airline reservation you've ever made. Also, it's used here on HN. And in Grammarly.
That's appeal to popularity. At least lisp is strongly typed. JS happened to be created first, and the world was stuck with it as Web grew and no other alternatives came out.
> JS ... is the most successful and important language in the world (probably in the history of programming),
I object, C is that.
javascripts success is an accident of history and we have paid a heavy price for it
null is considered billion dollar mistake but in JS there is 2 null so the statement is not incorrect :P
>> This feels like process immaturity or unfamiliarity.
On the contrary, I think it shows great maturity in the decision making process. Many highly experienced developers have stayed away from TypeScript for reasons like those mentioned in the article (mostly to do with the build environment, source mapping, versioning complexity, etc...) These are very significant problems and not worth the small benefits which static typing brings.
I just cannot consider this a reasonable stance.
There are places where no-typescript would be appropriate, but they’re vanishingly small. The idea that the benefits static typing brings are small is just laughable.
The reason this is such a hard choice is because static typing brings great benefits, so choosing to forgo that is not easy.
> not worth the small benefits which static typing brings.
pshh
Further, even if they drop typescript, this particular problem won't go away. The solution to this problem is the same regardless of whether typescript is in play. It's odd to count it as a problem with typescript.
This is enough reason for me to completely forget Deno. They clearly cannot write code or organize it without using classes, which is the core of their current error. The fact that they would choose that stupidity over the organizational benefits of interfaces and static types is not something I can reconcile.
remember deno is written by same person who wrote node js so please don't judge immediately.
That's even more reason to disregard it then
The technical problem is a class name in their code conflicting with a same named definition in their index.d.ts file closely related to that class. If they stopped using classes or changed those names to not be in collision this problem would be cured, which indicates it’s an edge case in their code they could easily fix but choose not to. Knowing that and that they blame the TS compiler for their code problem is cause enough to be judgemental.
Knowing they are aware they could easily fix this issue themselves but are instead dumping TS is cause for hesitation to invest in the project.
Here's the Deno Design document with the reasoning and some discussion about the decision: https://docs.google.com/document/d/1_WvwHl7BXUPmoiSeD8G83JmS...
This post adds little to what's already said there.
I'm a little shocked at some of the outcry in this thread. People are making it sound like they're switching from Rust to Ruby or extolling the virtues of types: TypeScript does absolutely nothing for you at runtime. There are no types, there are no type checks, its all the same guarantees as good ol' JavaScript. You still can't trust function parameters to be what they say. It's a Babel configuration with inline doc annotations.
If people are serious about types, then why isn't more front-end moving over to Elm, Reason, PureScript, OCaml etc? Hell, GWT is still out here even. TypeScript has convinced people they're getting the benefits of (strong?) types when they're just populating the auto-complete in VS Code.
Because runtime type checking is expensive. If most of your project is in TS then you will never hit type errors in runtime (we are yet to see after two years of development).
I have been using GWT, too hard to use comparing to typescript with pretty much same benefits.
TypeScript is really about type safety within the confines of your application. You can address the unsafety at the edges with something like io-ts.
Wholeheartedly agree and would like to point to another library that is capable of providing runtime typechecks: https://github.com/vriad/zod
It doesn't come with the fp-approach that io-ts takes, and has, in my opinion, significantly better error reporting. Just plugging this here because I believe that zod is grossly underused :)
But this is a niche application of TypeScript, most day-to-day front-end devs I've interviewed aren't reaching for fp-ts, let alone io-ts, whatever the benefits.
Even then, why not just use any one of Elm, PureScript, Reason, ScalaJS, etc? Why implement yet another FP runtime? If something like this is the surest way to make optimal use of TypeScript then I feel like we're just right back where we started.
For most devs, I'd wager they're still ending up writing all the same tests they were before TypeScript.
tsc even offers to just consume jsdoc annotations for crying out loud. If its just some kind of type convention sandbox, what did it really bring to the table?
Elm's got questionable support; I wouldn't feel comfortable recommending that at work, it'd be irresponsible.
PureScript I really like but it's a massive jump from JS/TS to PS/HS.
All of these languages are harder to abandon than a library in the same language you'll keep using if you decide against the paradigm down the road. Do I like this compromise? Not really, but it makes sense.
Also, advertising use of a functional language might open you up to candidates who wouldn't otherwise apply.
AFAIK Elm doesn’t perform runtime checks, does it? One benefit of types is auto-complete, of course. The other benefit is that knowing the type of your input you can successfully guide it through your system to an expected output. That’s how all statically typed languages work: they don’t have runtime checks. It’s not for nothing that teams switching to TypeScript see a decrease in runtime exceptions (speaking from experience). Our bug tracker was reduced by more than 80% after we finally completed the switch from JavaScript to TypeScript.
Elm doesn't need to perform runtime checks (apart from application boundaries like JSON parsing, where runtime checks are performed) because their type system is supposed to be sound, so you can't compile something that would have incorrect types at runtime. Or if you can, that's considered a bug in the compiler. That kind of sound type system has never been a goal for TypeScript.
Note that I'm not saying that Elm would be better than TS or any other language or anything like that, just commenting about the runtime checks. Obviously languages have their strengths and weaknesses (Elm has plenty of both) and TS has had good reasons to go with their design goals.
Static typing, by definition, does nothing for you at runtime.
I’m a long time fan of TS, but I think this is a very exciting decision —- I have always been of the opinion any reasonably large project should workout a doubt use TS, so hearing about how this goes for them in 2/5/10 years in terms of how easily people are able to maintain code they didn’t create, how readily large refactorings can be made, how often runtime type errors occur (not just the literal TypeError, but all the things TS can catch, like null checks, index typing checks, etc) will be quite interesting.
I wish them luck!
One note of concern though: in their design doc they say incremental compilation is the number one problem and list multi-minute compile times. That’s huge! I wouldn’t use TS either of it took minutes to compile my projects. However, I think there’s room for improvement in their tooling if they took some time to explore what other large TS projects do instead of just giving up on it entirely —- VSCode for instance has incremental compilation in hundreds of ms or less.
What a measured response!
They should just use deno to run their setup, there would be no compilation if they did that. ;)
Someone is trying to rewrite tsc in rust for speed up here - https://github.com/swc-project/swc
Cool project for runtime checking with ts - https://github.com/gcanti/io-ts
Edit: Remove unmaintained runtime type checking library.
Instead of ts-runtime, use io-ts (https://github.com/gcanti/io-ts). That one is actually maintained, unlike ts-runtime!
I found sweet spot for myself - flow with types in comments. As weird as it sounds it works for me on quite complex projects very well. Unlike typescript, which is language transpiler like coffeescript - flow is just typechecker with guarantee that after stripping types the output is valid js. It wouldn't work with ts, which generates runtime code ie. enums etc. Very good type inference means types appear as type declarations and when declaring functions and pretty much nowhere else. The code has interesting haskell'ish feel to it, ie. most of the code looks something like this:
const ofId /*: (Sql, number) => Promise<User> */ =
(sql, id) =>
...
I'm very happy with it after using it on quite complex projects, writing libraries (ie. functional combinators for parsers, assertions/runtime types, template sql generators; and the rest from apis, business logic to anything that is needed).Lack of libdefs is not a huge problem in my case. I have strong preference for shallow or no dependencies in projects and for things I use 3rd party code there are types or were converted from ts or simply added. Better support would help here but it was not a deal breaker.
Code editor support is not as good as ts but it does the job.
Another interesting effect is that arbitrarily deep npm linking is so much easier, the code is just js, doesn't need transpilation step, can be edited as is; I'm free to use any directory structure, ie. I often use root directory to drop files, they have natural require/import paths, no configuration etc.
For me, it's a joy to code like this.
typescript also supports type checking js code: https://www.typescriptlang.org/docs/handbook/type-checking-j...
I've found this very useful for gradually migrating a node.js project to a more maintainable state. Types also mean autocomplete works!
Additionally since it's typescript we can download the `@types/` packages for our dependencies and get type checking for those as well.
You can't do too many things with jsdoc, can you? Ie. generics are not supported or basic things like importing types from other file, right? Ergonomy/verbosity/look and feel of those types in jsdoc is a bit poor IMHO as well. It's absolutely not the same thing. With flow you get the whole flow, with jsdoc it seems some scraps of typechecking. Am I wrong?
Generics are supported via `@template` https://www.typescriptlang.org/docs/handbook/type-checking-j...
types can be imported either explicitly via `require()` or via the `@type {import("foo").Bar}`
There are definitely some limitations and caveats, like `Object` being aliased to `any` (I think this is being changed in a new version), but it's still way better than untyped JS, and having typescript integration is nice since our devs are already using typescript in other places.
Can even using things like https://github.com/typescript-eslint/typescript-eslint
Flow is both more advanced and faster than Typescript, but the community isn't as large, so Typescript continues to gain marketshare
If it supports many constructs, why they don't switch to using it in deno?
I assume most of the minutes-long compile times they are running into are because of type checking. Moving types to comments wouldn't help that.
I don't konow why they aren't separating type checking and dev builds from each other, but there is just absolutely no way simple TS to modern JS (no compiling to old ES5) conversion would take that long for a 10k LOC project, it must be the type checking. I'm using TS through Babel and it has been a breeze for much larger projects than that. Babel just strips away the TS types and we do type checks via editor integration and a separate CI step. Can't recommend this setup enough.
It's not only compile times, it's also runtime code it generates and issues it creates in some cases, article mentions it.
> It’s worth mentioning that Deno will stop using TypeScript only for the internal Deno code: the Deno user code will still be in TypeScript and thus type checked.
It seems it might be an issue with their development abilities or problem-solving motivation:
1. It seems that they write a ".d.ts" file manually in addition to using TypeScript for the code. This is dumb, since TypeScript generates the declarations automatically. However, for them "it was too much overhead and complexity when we attempted it before", which caused them to give up, a very dubious course of action.
2. They claim that changes take minutes to recompile, but TypeScript can compile incrementally, so this shouldn't happen assuming they are organizing their code properly. Also, you can just translate without type checking, which is no worse than using JavaScript instead.
3. They claim that "having two Body classes is obviously wrong" (?!). Of course having two classes with the same name in different namespaces/packages is perfectly fine in properly designed languages (including both JavaScript and TypeScript). Their "Header" shadowing problem also might be due to a lack of understanding of namespaces.
4. They seem to conflate JavaScript vs TypeScript with single file vs multiple files. Of course you can have a single TypeScript file or you can have multiple JavaScript files and bundle them with any JS bundler or just concatenate them.
Given that their codebase seems to be complex according to their compile time claims and that they don't seem particularly skilled given their claims, using a type-deficient language will most likely result in software full of bugs.
With regard to point 1, I think the reasoning is that they wanted precise control over their .d.ts file, since that's the public interface. This I understand, though I don't see why switching to JavaScript necessarily helps. Maybe it was tricky to get the TypeScript compiler to accept their hand-written .d.ts while also processing TypeScript? Which sounds more like a tooling problem than a language problem.
I'm with you on the rest of the points, though. I don't quite understand it, either. But then I'm not working in that codebase every day. Easy to criticize people from the outside!
I’m never one for developer hero worship, but I feel safe assuming that Ryan Dahl’s development abilities are not the issue here.
> 2. They claim that changes take minutes to recompile, but TypeScript can compile incrementally, so this shouldn't happen assuming they are organizing their code properly. Also, you can just translate without type checking, which is no worse than using JavaScript instead.
Interested to know how you're actually supposed to do this. I don't do much web development, but the few times I've had to dive into our typescript code at work, I end up just modifying the compiled javascript to debug things because the compile loop is painfully slow.
It's a relatively new thing
https://www.typescriptlang.org/docs/handbook/release-notes/t...
I don't remotely see TypeScript as the end state of statically typed JavaScript. I think it was the first major project to prove how static typing could work and benefit browser applications. Flow and TypeScript are just the first generation. In the future I expect the type system to be integrated with the runtime. While there are projects that give you this (Elm, Reason, Bridge.net, Fable, etc.), they are nowhere near as universal as TypeScript nor is that really their aim.
I am a newbie reason user. I like the language and ocaml ecosystem but it is just a bit of a pain to do anything practical with it. Soon you are writing a lot of js in reason. Compared to typescript, js and reason mixed code stings like a sharp contrast between sun and moon.
Until those languages make themselves feel just like js or completely remove excessive js interlop, they won't be as mainstream.
Huh, I don't share your experience at all. I maintain an F#-and-JS application and I'm constantly surprised by how well interpretation works. You literally just import F# code in JavaScript and use it, as well as the other way around.
Sure, if you want to make maximal use of the strong typing of F#, you'll have to annotate JS data as it comes in, but that is necessary complexity, not incidental. And if you're happy with having your F# code "dynamically typed", there's zero ceremony around importing JS stuff.
> I never have the class of bugs in my projects that people seem to laud about typing to solve. It’s kind of ridiculous
You do have that class of bug. That's like a cpp programmer saying they don't need smart-pointers because they never introduce memory leak bugs. You're a human.
> One of the issues mentioned is that they ended up with duplicate independent Body classes in two locations
... choice of programming languages is irrelevant here.
Needs "internally" at the end of the title.
Discussion from two weeks ago: https://news.ycombinator.com/item?id=23462506
Why remove it entirely rather than split off compilation and type checking? I’m not familiar with the Deno codebase, but a similar problem with large webpack projects is solved by having the type checking be an async process. This gives the best of both worlds as you transpiling alone is near instant.
As other's have pointed out, it really sounds like the deno devs were unfamiliar with what's available with build options for typescript. An unanswered question everyone is asking, why do they handwrite the .d.ts that can be autogenerated?
I used Typescript for 2 years, and I'm happy to report I'm dropping it and encouraging my team to do the same. Types are for compilers, not people, and personally I think there's more disadvantages than advantages re: time.
> Types are for compilers, not people [...]
This strikes me as a similar sentiment to “Requirements are for managers, not engineers”
> Types are for compilers, not people, and personally I think there's more disadvantages than advantages
The Haskell community strongly disagrees...
I dont know Haskell that well, but I thought it had strong static typing?
Though, Haskell figures out the types for you, instead of you typing them in, maybe thats a big difference. In Haskell, do you find you have to think about the types anyway, or can you code it like you would clojure?
I come from a clojure background, maybe that's why I don't enjoy TS. I find that large projects, so much code is un-necessary, people spend a lot of time troubleshooting types instead of building functionality. Of course it depends on the project. Social security #'s is a different scenario than something like a game or frivolous retail...
> Types are for compilers, not people, and personally I think there's more disadvantages than advantages re: time.
Hard disagree. Types are for people. They're for people to tell compilers what to tell people. Which is incredibly useful. They are first and foremost a communication and code-navigation/wayfinding tool—for people.
As for all this extra time some folks keep complaining about, we must be using TypeScript entirely differently, somehow. I don't get it at all. Its overhead is less than the time it saves me in typo-spotting alone, let alone all the other benefits. Takes 5%, gives back 20-30%. It's not even close. Maybe it's a problem for really, really slow typists? I'm not even some kind of editor wizard and it hardly slows me down. It can't be thinking up the type definitions since you need to do that anyway—right? I hope? And at that point you may as well write them down.
My experience is by definition anecdotal, but what I've found is as the team grows more and more work seems to focus on defining the types, futzing with the types, talking about the types instead of talking about features. I come from a Clojure/script background so I suppose I'm trying to say if (in building UI's) if you bake in strong immutability and a functional approach (like re-frame... but JS) types, to me, become less and less of a concern. Of course it's highly dependent on the business requirements.
I wish Dart was more popular as a JS alternative. I've been using it recently it's really surprisingly productive and fun.
Most of what Dart offers was addressed in ES2017 and beyond. I think it was released a little too late in my opinion.
Does Dart still allow you to compile to JS or was that feature dropped?
It must; the SASS reference implementation is written in Dart and the npm package is transpired from that.
So it happens again, yet another project discovers that whatever improvements a guest language brings into a platform, using it also has its costs versus using the main language of the platform.
Using JS instead of TypeScript is very short-sighted and they will regret it, eventually. Sounds like they got frustrated and gave up.
Their arguments remind me of someone saying they want to use Assembly Language instead of C++, because assemblers are faster than compilers, or to not have to worry about memory heap issues, etc.
All you're doing by switching from TS to JS, is trading one set of minor problems (which are solvable) to a more vast set of even larger problems that are NOT solvable.
Spoken like someone who's never solved problems with medium-to-large scale JS projects... criticising people who have.
Here's a pretty sizable project I wrote in pure TypeScript:
https://github.com/Clay-Ferguson/quantizr
I have 5 years experience in TS and 20 in JS. Trust me, if you don't yet understand the value of type-safety, it's only because you haven't lived long enough yet.
I do understand the value, thanks mostly to Haskell. I also know that (language- or tool-enforced) type safety and type discipline are separable concerns. I also understand when the former gets in the way, thanks to JS, TS, Rust, Lisp, and projects large and small, slow and then fast, fast and then slow, slow and then slow, and fast and then fast.
Every developer, regardless of skill level, makes mistakes and typos. The beauty of type-safety in TypeScript is that the compiler catches it instantly, in a way that is simply humanly impossible.
If I misspell something, or provide the wrong argument type to a method, or have args in wrong order, etc, it's caught instantly.
With JS you can have a typo that causes user malfunctions for YEARS before being found by a developer and fixed. Any developer who's done many years of both TS and JS would never in a million years consider going back to JS. Absolutely out of the question.
> Any developer who's done many years of both TS and JS would never in a million years consider going back to JS.
Except, apparently, for the topic of this article.
> If I misspell something, or provide the wrong argument type to a method, or have args in wrong order, etc, it's caught instantly.
Yes, I've heard the pitch before. I've even given it more than a few times.
Of course, if both of your arguments happen to be 64-bit floats, then the type system won't help you much if you get them in the wrong order.
However, when you want to change that function to take a closure instead of a number, the type system can be invisible or it can fight you. Some of us love the structure that a type system can provide. Some of us, like the one who started this website we're on now, also appreciate the power of languages that get out of your way and let you make your own brilliant mistakes. And some of us can appreciate the beauty of different language designs and approaches, and try to rise above dogma. Which, if you've been in this line of work for 20+ years, should be you.
> Except, apparently, for the topic of this article.
Well, Deno devs did try to use TypeScript, and just ran into some challenges, and decided to throw the baby out with the bath water. I've seen this a lot in my 30yrs exp.: some developer/team runs into problems, gets frustrated, gives up, and decides the best decision is to remove some important piece rather than solve the actual problems.
The reason Deno is giving up TypeScript is representative of failure, and not an indication them wanting JS instead of TS. What they want is TS.
The rest of your reply is just stating some minor imperfections that are a billion miles from invalidating TS. And yeah, there's a place for JavaScript still, for small-scale tinkering, or perhaps even prototypes with only a few hundred lines of code. Any large scale project in JavaScript (not TS) is simply unfathomable to any modern developer worth his salt.
You're a dogmatic true believer, and it's rarely worth arguing with dogmatic true believers. Just notice that you threw everyone that disagrees with you (or rather, that comprehends a wider range of circumstances than you do) under the bus as "not worth [our] salt". That was not the right thing to say.
And you dismiss my reply (including the part where I point out that the website we are on was first developed in a Lisp) as "some minor imperfections". It's like you're satirizing the tunnel vision of the fundamentalist.
And, true to form, you "know" what the deno team wants better than they themselves do! I hope you can come back to this thread in a year or two with some perspective.
In the above discussion I focused on the technologies, programming languages, and the core of the technical issue. You seem to focus on personalities, feelings, and emotions. To each his own, I guess.
And about me knowing Deno did want to, and did attempt to use TypeScript: the way I know that is because I read the article, lol. Apparently you did not.
I did read the article, and also the design doc which I linked in my top-level comment.
The facts are that they started with TypeScript and moved away (for a particular internal component). The interpretation of that as wanting to use it and failing is yours. You could just as well see it as having made a mistake and then realizing it. But all of these interpretations, by those of us who didn't have to make the choice and weren't there when it was made, aren't very helpful.
That's correct. They failed to get TypeScript to work. Thanks for reading that.
That is one key thing I see a disconnect with. I definitely can see the value in having static types in a long-lived/large js project, but at the same time 1) how long does the average js project really stay relevant, 2) people have got by just fine w/o it so far. I’m kind of mixed on it, but for my new web app I’m working on I decided to use vanilla js because it feels much more efficient.
And if you converted your code to TypeScript you'd immediately find the 100 or 1000 bugs you have that you're just unaware of until they bite. People who have done such a conversion before know this, and unanimously will agree. Those who have't are blissfully ignorant.
This is a great victory for Ecmascript. Typescript is a great hinting support language, I use it with JsDoc to check my (not transpired, vanilla js) code. But it cannot replace JavaScript and is not a JavaScript superset. I think If anyone what to accept the drawbacks of have transpiration of source files can choose better alternative to typescript.
Everyone is drawing conclusions without much context. Read the design doc[0].
[0]: https://docs.google.com/document/d/1_WvwHl7BXUPmoiSeD8G83JmS...
I can fully understand that an additional tool layer can cause additional problems, but static type checking is a large quality win for large projects. There are workarounds to achieve similar results:
(1) Use a faster bundler like esbuild, here vite's similar considerations [1]
(2) Use Flow [2] and just strip it away before distribution like this Babel module [3]
---
[1] https://github.com/vitejs/vite#typescript
[3] https://babeljs.io/docs/en/babel-plugin-transform-flow-strip...
"Always bet on JavaScript" holds true, I guess.
There are tools to transpile typescript only, without doing typechecking, which dramatically reduces "compile time." It's very useful for a quick development iteration cycle, and then do a full type checking pass before merging and during CI.
I'm doing a medium/large project in Coffeescript 2 and it's totally awesome. Rarely a type related bug and I'm progressing waaay faster than having to deal with TS in my way.
But for anyone enjoying to specify their types in detail, have fun!
wow that’s cool to hear! I read about coffee 2 awhile ago and then heard nothing of it. I used to love coffeescript, arguably more than vanilla js, but forces that be led me to move on.
are you working with a team? if so was it easy to get buy-in?
Was using JS for about 6 yrs now and decided will start using TS for a new Node.js project. Admitted it has its warts ... hit my first bottleneck rightaway when parsing the request query param. TS Express bindings declare it as string | string[] | ParsedQs | ParsedQs[]. Ok extract it 'as' string and move on. But I find as I am using it more and more it is getting better (or I am getting more disciplined!) .. maybe I am reading this wrong re the long compile time reported, could the code not be broken into modules so the compile is more isolated ??
just a heads up, casting `as string` isn't safe since the request param could turn out to be an array.
If the request ends up with the query param as an array, there isn't a runtime to validate the cast and now the variable is typed as `string` but is actually `string[]`.
I think a safer approach is to use a validation library or refine the type with an if stmt and returning an error when it isn't a string.
I use the following lint to prevent all casts except `as const`: https://github.com/typescript-eslint/typescript-eslint/blob/...
Thanks for the headsup. I did realize that. It was a specific case of pulling a username from the query .. checking out the library ..
It seems weird to ask other projects to use Typescript when running on Deno when Deno isn't using typescript internally? If you're the Deno team wouldn't you want to dogfood Typescript?
Different use cases = different technologies.
Nobody's asking them to.
This seems to lend more credit to ReasonML. Compile times are faster and it doesn't bring the associated complexity of object types while still retaining the benefits of static typing.
Thank you.
Finally people are speaking out against the madness of TypeScript.
Don't get me wrong. It is a technical achievement to put a static type system on top of JavaScript. And for libraries, it is useful. It let's the users of the library get hints and direction from an editor like Visual Studio.
But as a language. It is just not good. No way anyone would end up with a design like that had it been built from scratch without going through JavaScript first.
Remember when Java did generics and got flak because of type erasure? Compare with TypeScript ...
I just hope in 5 years we're not seeing a talk saying that in retrospective, dropping static types was a huge error... and DoNe is a new project to fix issues like that!
(I'm just referring to this nice talk about the regretful mistakes done in Node: https://youtu.be/M3BM9TB-8yA)
Typescript may not work for all types of applications - in fact there is no language that does. So picking one project and generalizing it often comes out of inexperience.
As a counter example, VSCode is easily bigger than the Deno codebase. Again, that doesn't mean it's good for your project.
You know when you say a word over and over again and it starts to lose meaning?
Well, I didn't have a clue what Deno was before, but now it's barely letters in a screen. This post says Deno way too much. Deno.
> While TypeScript is sometimes seen as an improved version of JavaScript, this case is showing that in fact, it’s not. It has flaws like any other language.
This is not a language flaw. It is a tooling problem.
I've migrated to Typescript and have been using it for about 2 years now. Maybe 1.5...
TS is the best language I've used. It supports frontend and backend and strict typing and it's scalable so I can refactor and know that my code still works.
The one thing its not good at is ML where Python is better but that's mostly because Python has better library support (not language design).
Here's the deal. When dealing with a large amount of code 80% of your dev time is spent maintaining code - NOT writing new code.
You can save a lot of time now writing new code and not using strict typing. OR you can spend a little bit of time now, maintaining your types, and save a MASSIVE amount of time later.
> - TypeScript compile time when changing files takes several minutes, making continuous compiling an excruciatingly slow process
I have a HUGE typescript repo and using a Macbook Pro from 2015...
With --incremental and --watch my build takes like 5 seconds. About 1 minute on the first build then about 5 seconds after that.
If your build is taking a long time - you're doing something wrong.
> The internal code and runtime TypeScript declarations must be manually kept in sync since the TypeScript Compiler isn’t helpful to generate the d.ts files
What? How? That doesn't make any sense. You're doing something wrong here. If all the code is in typescript, you have no additional work to do. If it's in JS you just have to write your own .d.ts files manually.
Honestly it seems like this team just needs to sit down and understand how their tools actually work.
The one issue where Typescript DOES kind of suck is when dealing with webpack, typemaps, and types.
Many older projects just don't publish types and if you rely on them, and they refuse to publish types, you're going to be in a bit of pain.
You can write your own types though and we've been doing this internally and for some repos just forking them so it's a bit easier to work with them. They usually lag on publishing their types.
If you want to avoid all this pain you can just use webpack for your build system and Typescript for your code. We use lerna to build a multi-module system with --hoist to avoid duplicate dependencies.
https://github.com/burtonator/polar-bookshelf
... is the project we're working on if you want to check it out. Our internal build system isn't fully published yet as we're in the process of reworking it but we're open source so you can take a look if you want.
I'm wondering about "--watch" too... My projects are compiled in the background, like pretty much instantly. The only time I wait is when I restart the applications.
But I suppose they are aware of this flag.
Is there a reason we can ONLY use JavaScript in the browser? The world would immediately become better if we added a different language compiler on in instead.
Has anyone else experienced these issues? This reads more like product placement for Deno than a sincere criticism of TS.
I've definitely noticed that compiling typescript is slow and extremely resource hungry. It's amusing to me that our "web" stack is the most resource intensive part of our entire codebase at work.
A sign of the times I guess that a build system requires 8gb of ram to run. Could be we're doing something wrong, but from what I understand we're using a pretty vanilla setup.
Unfortunately the state of web dev in 2020 is such that using a vanilla "best practice" setup is very much doing something wrong.
> While TypeScript is sometimes seen as an improved version of JavaScript, this case is showing that in fact, it’s not.
Woah, woah, hold on. This case is showing that in the very specific, atypical case the Deno team are using it in, TypeScript is not the right fit.
I’d rather read something that actually interviews the Deno folks about what they are doing, the underlying document is a pretty free ranging discussion and this writeup is making a few assumptions.
Lawd, the number of times people write an extensive essay detailing how a particular tool didn’t fit their culture, processes, and circumstances, then explain why it’s either irredeemably broken or conversely, that failing to adopt the tool is professional malpractice.
N=1. That is all.
May as well drop tests and code reviews if it feels like it's slowing you down. For one-person or very small teams who have full context of a'll changes this can actually work very well. It's with more contributors participating in a mature project that you'd wish these things weren't dropped. Types can be added later so it's not like using php and later wishing you'd used Kotlin.
I'll add a datapoint of an analogous case. I updated a legacy java 1.x codebase that was running java 6/7 without generics. Having spent a small amount of effort over a course of months, all the type annotations were updated. It uncovered exactly one bug. The main improvement is for quickly gaining context in unfamiliar code and being able to enable warnings for newly written code without noisy error messages.
I'm stoked on this change, frankly the TS layer being included in Deno felt like a mistake from the get-go and I'm glad they've come around on it. I've seen many transpile-to-JS languages come and go. Javascript is eternal.
(Though I also think TS is a verbose mess made so that enterprise programmers/managers can feel safe, but even if it was great I still think this would have been a good choice)
When Deno initially mentioned they run Typescript directly I was intrigued. It’s like running GCC every time you want to invoke the script.
That being said I run ts-node all the time with transpile-only and that is decently fast. Even on production where the minimal cost is incurred once when loading the module.
As for their problems mentioned on the document. That Header class has a .d.ts conflict on an interface. That could be solved with having namespaces in .d.ts or having I prefix for class interfaces. We do this all the time in our codebase.
I’m not entirely sure why they have two copies of things. The doc doesn’t give much detail.
If you want things to be fast like nodejs, then the other option is to use //@ts-check comments on JS files, or with compiler allowJS and checkJS settings. Webpack checks all their JS.
TSC now also has an option to automatically generate .d.ts from JS files with jsdoc comments. With declarationOnly compiler flag. Many existing JS projects already do that.
So TLDR is. You don’t have to ditch Typescript totally. Typescript can purely just be a checker that you run at CI time and it will work quite well with existing JS code. Although if you want super strict safety the .ts syntax is less verbose and nicer to write. Even then transpile only mode is much faster than running full tsc.
Remember: TS is a superset of JS. All JS is valid typescript. Sometimes we gotta structure the JS properly and that’s where the issue is rather than the typesystem.
I felt like the article and associated google doc were fishing for reasons to remove TS until ry finally mentioned "typescript provides an extra 500 lines and the namespaces make the code harder to reason with (V8 ingests these files directly)". IMO that was the only solid reason for the change.
Always bet on Javascript.
oh I thought at first that this meant they were dropping _support for_ typescript, not that they were stopping using ts under the hood.
Getting closer to the metal seems good!
HN gods, an off topic question.
Would Deno become the new Node?
Do you see a vibrant ecosystem building around Deno?
What I am interested to know primarily is, is the architecture / stack / goals and vision that resulted in Deno viable in the long term?
Deno's main selling point over Node.js seems to be some dubious sandboxing. Unlikely to be compelling enough for people to rewrite their applications from using Node's stdlib to Deno's.
Personally, it makes me cringe to see hard-coded HTTP URLs in source code files for loading dependencies. They present it like we're stupid for using package managers all this time. What used to be a simple command line option (changing a package repo) is now a thousand file edit. Excellent.
Has anyone seen any comments by the TS team on this? Maybe they would be amenable to helping out if the Deno team contacted them.
Honestly, what is a meaningful answer when someone blames language for problem with having two separate classes with the same name?
Due respect, these are issues with how the Deno team uses Typescript, not with the language itself.
> TypeScript compile time when changing files takes several minutes, making continuous compiling an excruciatingly slow process
Umm, you can compile single files, and serve them individually. It's no different from bundling (e.g. with webpack) Javascript.
> The Typescript structure that they’re using in the source files that create the actual Deno executable and the user-facing APIs is creating runtime performance problems
Then use a better structure?
? TypeScript isn’t proving itself helpful to organize Deno code. On the contrary, the Deno team is experiencing the opposite effect. One of the issues mentioned is that they ended up with duplicate independent Body classes in two locations https://github.com/denoland/deno/issues/4748
Then consolidate the two classes...? How is the the language's fault?
> The internal code and runtime TypeScript declarations must be manually kept in sync since the TypeScript Compiler isn’t helpful to generate the d.ts files
Well, it can be. Fix your build rules.
> They’re maintaining two TS compiler hosts: one for the internal Deno code and another other for external user code even though both have a similar goal
Again, not the language's fault.
---
We've been using Typescript for a couple of years now, and it's been great. By trying to do things the right way, it actually forces us to organize our code better. I think the Deno project would benefit from refactoring their code to solve their issues, instead of blaming the tools.
Your main point seems to be that these problems aren’t the language’s fault. But I don’t see the Deno team claiming that to be the case. There’s nothing wrong with choosing a language that works with how your team likes to develop software, and rejecting a language that doesn’t work well for your team. Doesn’t need to be anyone’s “fault.”
It's entirely valid for them to decide they don't want to change their ways. However, it is frequent that technologies will be rejected because the requisite learning to understand why and how to best use the technology is not done. A common example of this (in my observation and ignoring the application of the technology where it's entirely unnecessary) is NoSql where teams have attempted to use those databases as they used their relational counterparts which obviously didn't work because they didn't shift how they were thinking about using storage and structuring their systems. Anyway, that was how I read the GPs post, as attempting to note that the Deno team may not have pushed through the mental shift required to really get the most out of TypeScript.
[edit: not trying to take a stance in support of the GPS post or either side of this discussion, to be clear]
That's true, but I think when you choose to use a programming language, you essentially commit to doing things its way, otherwise you end up dealing with lots of friction and having to reinvent a lot of wheels. Like the Deno team claim they do.
Taking up Typescript then ignoring best practices when trying to use it is unfortunate. This kind of thing would be a teaching moment for a junior engineer.
It's like saying you don't want to use a dishwasher because if you stack bowls on top of each other, it doesn't clean them well. Well, a dishwasher has its faults - a lot of dishes are not dishwasher-safe, etc. - but your reason kind of misses the point.
> not the languages's fault.
I think that's the whole point. It's not the right tool for their specific goal.
In their design doc[0], they agree that Rust glue code should not be written in TS: compiled code "full of weird namespaces."
From the design doc discussion[0]:
ry: manually managing the d.ts files has been great - it's very much part of the public interface - we need to have 100% control over it we do not want random compiler-generated __namespace0123 in there This is the same situation - but for the bundle It's not good that we do not have visibility nor control over what code is in there. for example, the TS compiler worker, has 15k lines of code in its bundle - EXCLUDING typescript.js TS compiler worker is about 500 line thing that interfaces between ops and TSC this is caused by our attempt to "self host" the internal code self hosting is cute - but if it's effecting performance and the ability to make improvements - it's an unnecessary feature https://gist.github.com/ry/a6d4b1466158d82750a6447342fd3af4 ^--- here is what we ship for the compiler worker we call this code every time deno runs
lucacasonato: Ok, wow. I hadn't seen this. That changes things...
ry: does the compiler worker really need to generate a UUID? https://gist.github.com/ry/a6d4b1466158d82750a6447342fd3af4#... (no) yes, this is fixable within the current system .. but the point is that we're abstracting away the important parts V8 does not run typescript. It runs JS. We need to have a good handle on the JS we ship If we don't try to self-host, we don't need a sourcemap for the internal code. There's 1mb off the executable right there. The point is the internal typescript comes at a cost - and that cost is too high.
lucacasonato: So the actual issue is the bundling and opaqueness that that brings with it. It makes sense to stick to pure JS in that case. Its annoying that type checking is gone, but youre right. This is not the kind of code that should be in the runtime.
ry: not like the code isn't full of "!" anyway. TS is great, but it gives a false sense of security.
[0]: https://docs.google.com/document/d/1_WvwHl7BXUPmoiSeD8G83JmS...
The compiled 'mess' that is shipped in the runtime is mostly due to SystemJS, not TypeScript - it doesn't handle modules, and compiles to very clean code if you target a recent ES version. I'm confused as to how dropping TS will help with the code emitted for modules.
Is SystemJS still a thing? What's their point now that browsers support ESM natively?
Deno != browser
I know that. What eludes me is what advantages SystemJS brings over ESM, for browser runtimes and server runtimes (node, deno)…
IIRC SystemJS can be used without any transpilation at runtime. ESM cannot (unless natively supported of course, like it is in browsers)
These two have me confused:
"TypeScript compile time when changing files takes several minutes, making continuous compiling an excruciatingly slow process"
and
"The internal code and runtime TypeScript declarations must be manually kept in sync since the TypeScript Compiler isn’t helpful to generate the d.ts files"
If you're compiling Typescript, the .d.ts files are output by the compiler. The only time you need to manually keep them in sync is when you're writing .js and manually writing the .d.ts.
Why Deno ?
Deno Deno deno deNo deNodeNodeNo...
That wasn't a question about the naming.
You might need to say a bit more about what it is a question about if you want an answer.
"Why X ?" is a common shorthand for "What is the raison d'être of X ?"
Well, in all the initial presentations Ryan Dahl gave about Deno, he phrased it as solving the things he'd come to realise he hated about Node. So that's what I take as the raison d'être of Deno - taking the lessons he'd learned from some years mainly coding Go and thinking about what he'd learnt from Node, and fixing what he could. Here's the classic video on the topic: https://www.youtube.com/watch?v=M3BM9TB-8yA
I’m very perplexed about the reasoning.
Aside from the compiling takes time issue, the rest sounds like trolling.
If the code was organized in a way which is inefficient and confusing, I fail to see why checking types at runtime instead of compile types improves the structure. It’s a completely separate problem.
Yeah. Same same. Not working, so let’s just fix it by creating another ecosystem instead of fixing compiletimes etc.
I will refuse deno. Too much ego in JavaScript-land. “Everybody wants to be like Mike”. Errr Linus... Lowrey
Deno is made by the guy who made Node. So no change in notoriety there.
> TypeScript compile time when changing files takes several minutes, making continuous compiling an excruciatingly slow process
They must be doing something horribly wrong, because tsc takes literally 1 second for my 3KLOC codebase[1] in incremental mode.
We were actually considering Deno because of its TypeScript support. We have a sizeable TypeScript codebase written for Node. This will probably make us more likely to stay in Node.
EDIT: I didn't read the article thoroughly. It looks like they're still supporting Typescript user code.
In the design doc, you can read this disclaimer:
> Most people don't have the context to understand this narrow technical document - it is only applicable to a very particular, very technical situation in the internals of Deno. This is not at all a reflection on the usefulness of TypeScript in general. It's not a discussion about any publicly visible interface in Deno. Deno, of course, will support TypeScript forever. A website or server written in TypeScript is a very very different type of program than Deno - maybe much more so than novice programmers can appreciate - little of Deno is written in TypeScript. The target audience is the 5 to 10 people who work on this particular internal system. Please don't draw any broader conclusions.
You can't just run your typed node.js app in deno.
(Almost) all npm packages that are written in typescript expose .js and then .d.ts files, so you can't "just import the .ts". This is because of huge variances in tsconfig.json files.
Thank God, I would really appreciate this. The TypeScript usage was the one thing that I didn't like about Deno.
Why add complexity to a new project which starts from scratch? JavaScript is good enough and there's no need to make it confusing by adding another layer.
> JavaScript is good enough and there's no need to make it confusing by adding another layer.
To some people, JS itself is relatively confusing, and TypeScript reduces that confusion.
EDIT: And... someone's clarification is saying this is internal framework code, not userland support for TS. Seems like a non-issue, really. They don't want to use it, but want to provide support for others to use it in their projects.
You can use JavaScript with Deno. Nobody is forcing you to use TypeScript.
This doesn't change anything, it's for their internals. Why anyone would ditch static typing on a large collaborative project is beyond me though.
This is talking about the internal Deno code. The user facing side will still support TypeScript, though you’re also free to not use it if you want.