I've been around long enough that "safe" gave way to "productivity" and back to "safe". There's kind of a nascent ethos of being "better" in each new generation that just results in these pendulum effects.
The overall effect seems to be enormously positive. I can now bounce between several completely valid build environments, ecosystems, and languages for a given project depending on what is required. But make no mistake. Our kids will probably look at us like we're crazy as they embrace the 2040 equivalent of JavaScript and Python again.
I’ve been there, done that, and worked most of my career in dynamic languages. There’s just better tools available today. There’s no going back for me.
Python with types or TypeScript is as dynamic as I’m willing to go now, and only as a last resort.
seems "safe" would go over better in recession times, while "productivity" is just a nicer way of saying "move fast"
Instead of worrying about types, why not worry about the actual code quality?
Half of all typescript I've seen uses "any", not to mention the fact that it obsfuscates what's actually running in the browser and forces an unnecessary build step for things that aren't "web apps".
I'd argue that a sign of good code quality is using types even in languages and contexts where you don't have to.
PHP is technically still a duck-typed language, but the community has embraced its relatively new strict typing features with open arms and the PHP ecosystem is all the much better for it.
But you talk about code quality... Honestly if I've got a tricky task the first thing I'll do now is write the types for it, they'll keep me on the right path.
Example: Next week's job is to add analytics to a codebase (I get all the glamorous tasks - well, actually just all the tasks), and the geniuses with the spreadsheets have come up with like 100 different events to track, each with a selection of sometimes-overlapping properties.
I've done this before in plain JS and it was unpleasant. In TS once I have the types nailed down the rest is easy - and when they inevitably change their minds about something the week after next I just alter the types to match and then follow the errors until it works again.
You're saying that half of the projects you've seen successfully adopted strict typing? And others use an occasional escape hatch, but still try to introduce reasonable typing? That sounds like a success story to me.
I don't understand how you think it obfuscates what is actually running in the browser.
Nearly all non-trivial web projects have a build step even if they aren't "web apps". But I agree it would be nice to at least have the option to avoid it. There is a JavaScript proposal going through that should fix that.
I have worked on multiple typescript projects that had terrible code quality. Types do not make you write SOLID code.
I find functional programming and well-used functional patterns do result in higher quality code. Typescript’s type system makes writing functional code more difficult. The documentation even recommends against it[1].
IMO typescript is easy to prescribe as a panacea, “just use typescript”, whereas understanding how to write SOLID code takes time.
[1] https://www.typescriptlang.org/docs/handbook/typescript-in-5...
So if you’re using it, you aren’t really using typescript, you’re disabling typescript and saying “I want to write this part in plain JavaScript.”
When typing is applied gradually throughout a codebase it can sometimes manifest as the worst of both world and a complete argument should at least acknowledge that as well as the impact of bad typing on codebases.
- Worse type error messages, as the type system has to be more complicated to handle the sorts of patterns that are common in untyped code.
- You can still get type errors at runtime in your typed code, if it interacts with untyped code, because it isn't feasible to validate all types on the boundary. You're only guaranteed no runtime type errors if all of your code is typed.
- The migration path from untyped to typed isn't always easy. Depending on how your code is organized, it's possible to have correct untyped code such that there do not exist type annotations you could add to it that would make it type check.
If types are to data flow what structured programming is to control flow, it's a bit like being able to call into unsafe functions that can corrupt your stack. You could waste hours trying to trace the flow of execution and being completely stumped by your code's behaviour, looking at stack traces that make no sense...
Furthering that analogy, like how a structured programming language restricts control flow to specific structures as compared to free-form branches and jumps, certain interfaces and patterns that you can get away with in a dynamic context can't be expressed (or expressed cleanly) in a statically typed language. Just as your average Java programmer doesn't usually feel constricted by the inability to write Duff's Device in their language of choice, once you get good at TypeScript you rarely feel inclined to construct dynamic interfaces, but JS developers...a world where static typing isn't universally enforced, especially if you're working with a bunch of JS devs who don't fully embrace static typing, encourages the construction of difficult-to-type APIs. This then feeds back into the first issue: reasoning about type integrity when using these APIs becomes painfully difficult.
Here's a writeup on it. https://www.onux.com/jspp/tutorials/type-system#Appendix-B
> The problem is not as simple as taking the ECMAScript grammar and augmenting it with type annotations. There's a reason that Microsoft (TypeScript, Safe TypeScript), Google (AtScript, SoundScript), and Facebook (Flow) have all collectively attempted this problem and came up short.
It continues for a while...
To compound matters, none of the TypeScript devs I've worked with have any experience with type systems. They don't think in terms of interfaces. They are still ball-of-mud developers. They did not come from Java or C/C++ or even Haskell. They came from Python or Ruby.
I'd also caution people about using third party types (i.e. DefinitelyTyped). These are often not correct because the underlying library is not in TS and does not have type information. You will pull your hair out when the library does not match the type definitions. These third party definitions can introduce bugs into your code. They can falsely claim that some field exists on an object which, in fact, does not. Your IDE will happily autocomplete to the invalid field, TS will happily compile it, and your JS run-time will unhappily crash.
Typing complex business domains and interactions is hard. Most developers don’t have a lot of experience with it or the time to do it properly as they produce features. It doesn’t help that many developers start their career with untyped languages and transition into typed languages without learning it properly.
Typescript is a great example because a lot of frontend developers may have only ever worked in JavaScript and have absolutely no foundation to build on but trial and error on your companies production codebase.
YES YES YES. I'm witnessing this nightmare with a project that started out as untyped and now we're adding mypy to it because without typing it is difficult to understand and work on. 2 million lines of untyped python.
It's basically a huge technical debt and I doubt we'll ever get to the point where we can enforce this in CI
because for a long time there were no mainstream languages with a good enough type system.
Rinse and repeat.
C++ used to suffer from "for" loops with insanely long type declarations for iterator variables. "auto" fixed that.
Inter-function type inference, while technically possible, is just too confusing for people reading the code. So that went away. Mostly, type inference is now forward only. Inverse type inference through long chains is, again, possible but too confusing.
Explicit typing of structure fields and function parameters allows automatic generation of reasonably useful documentation. That gives programmers anchor points at which they can see types.
So this has become a solved problem for compiled languages.
Javascript frustrates me just as much as the grumpy old man in the article. That said, I once sat down and asked myself, "self, why was it okay to live through the php years yet you despise javascript for being the same way?" And then it dawned on me, my involvement in php projects forced me to have a low-level understanding of the language that I never acquired with javascript.
The consequence for me is that javascript is still full of voodoo and dark magic, all very frustrating and bowel irritating. But that's not the fault of the language, that's the fault of the knucklehead trying to use it without really digging into the internals and understanding how it should be used. That would be me.
Not learning how javascript internals work and complaining about javascript is no different than when Mongo first came out, and folks shoved third normal form schemas in there and complained loudly that Mongo was a lousy RDBMS. It's not an RDBMS, mate.
If anything this article instead implies that typescript means you don't have to bother learning javascript internals. Do not recommend.
HN Guidelines: “If the title includes the name of the site, please take it out, because the site name will be displayed after the link.
If the title contains a gratuitous number or number + adjective, we'd appreciate it if you'd crop it. E.g. translate "10 Ways To Do X" to "How To Do X," and "14 Amazing Ys" to "Ys." Exception: when the number is meaningful, e.g. "The 5 Platonic Solids."
Otherwise please use the original title, unless it is misleading or linkbait; don't editorialize.”
I'm looking forward to the launch of Zig, that should be a good choice for WASM. Only if I could get a pytorch-like interface in Zig now...
I suspect that even Common Lisp wasn't the first industrial language to implement gradual typing, but I can't remember any earlier ones.
Makes it easy to fix and refactor things early on and improve things from a developer experience and interface perspective.
I push implementing a function as far out as possible, when the entire structure of the program becomes clear.
This hack easily makes me 10x more productive. Plus I don’t share the same annoyances with types and TypeScript for example that other devs face. Once it’s set up (just adding a tsconfig file and a package file) the type system just sort of disappears — I mean, I rarely fight with it.
I do agree though that most of the complaints with these systems, languages, and tools really come from the vast amount of competing “getting started” and build guides that always seem to get out of date or use some radical new way of doing things that upsets the whole ecosystem. There have been so many changes in this regard. That, I will say, I don’t have an answer for.
The main drawback I've fought with is that when you're doing something complicated - e.g. extending or decorating a module imported from elsewhere - it can be hairy to convince the editor to infer what's happening. The other one is I've never found a good way to author an event emitter, such that you get inference and type checks on code subscribing to the events. But there could be solutions to both points that I've been missing.
But it's completely feasible to use dynamic languages for non-trivial applications. I think it's fair to say that Hacker News is not a trivial application and it's written in a Lisp dialect called Arc.
The biggest advantage of dynamic languages is probably that they are usually more concise. Which can lend itself to a more elegant expression of intent.
Another advantage might be more flexibility reducing the tendency to add boilerplate or a lot of schema-specific code. And I am aware that many people consider a lack of schemas to be the worst thing ever. But at least they are flexible.
And yes I am aware that static types can eliminate errors at compile time. Those types of advantages don't completely invalidate the use of untyped languages.
// a DTO that handles the creation of some kind of resource
...
@IsArray()
@ArrayMinSize(1)
@IsString({ each: true })
@ApiProperty({
example: ['software', 'maths'],
})
tags: string[]
That's real code. Since the TS types gets erased when the code is transpiled to JS, one has to annotate the whole thing just to be sure the clients are not sending us invalid data. And the validation via annotations couldn't be more cumbersome. 90% of the code in the DTO file is annotations. Reminds me Java from 10 years ago.Typed languages offer some efficiencies, and can, if properly used, help prevent entire classes of footguns, but they do require a bit of planning. I've always wished I could do the same "gradual type" thing with Pascal, Basic, etc. As the program is run, the types are checked, and slowly baked in automatically.
Why mention memory allocation at all? There are plenty of typed languages that have automatic garbage collection and handle strings just fine.
Go (Golang) comes to mind as a superb example of a typed language in which string handling is a breeze.
JavaScript, Python, PHP, Ruby etc fill a niche. Personally I love strongly typed languages, but I get why people don't want to deal with it. I am old school and do not use an IDE, so for me strong typing is a must.
I only ask because I use Sublime Text but the most I use is the file browser sidebar and syntax highlighting. I don't use any linters.
I started with Ruby on Rails and Textmate and I've never needed anything fancy, even for 500k line Rails apps.
I use GVIM, no plugins. syntax highlighting is fine and file browser too, but once you start getting into autocomplete and plugins that too much I think. the IDE should not be a replacement for a poorly designed language, and that's what they have become I think.
I, too, prefer to avoid using an IDE. I appreciate strong typing, but I certainly don't feel that loosely or untyped languages are made more difficult to use by not using an IDE.
function hello(a, b) {
return a + b;
}
what the hell are "a" and "b"? numbers? strings? something else? no thank you.This is definitely an advantage! No dispute here. But whether static types make programs safer and their architecture cleaner is something in need to be proven empirically. And as others already wrote: There is a reason why dynamic scripting languages became popular.
The language which solves this will allow people to select the level of type abstraction on a per task basis, while retaining full performance. It will be nice when we get this, but no language is even close.
The article also touches on Typescript-in-JSDoc, but that can get really ugly with complex types and there are a few things I just couldn't figure out how to do when I gave it a proper shot last year.
On a large project, a lot of discipline is needed to make sure typing gets used everywhere.
Even worse, when you have a prototype that morphs into a large enterprise application, someone needs to go back and fill in all the types. This can be a struggle if everyone is gone.
basically this just kicks technical debt down the road.
What is not over is the complexity people inflict on themselves trying to model a non-trivial, changing data model with concrete types.
> velocity wasn’t a top concern, safety was
Not true. Velocity was as much of a top concern back then as it is today.
however it does nothing to address main issue plaguing software since the dawn of time: apathetic and/or adversarial engineers.
the problem has always been people and the ways of organizing and incentivizing them to build large complex works.
pl choice hasn’t ever mattered much, still doesn’t, and likely never will.