Hacker News new | ask | show | jobs
by digging 551 days ago
Honestly, yes, I'm curious to hear that perspective. The negative responses to "TypeScript makes JS programming fun and easy" are always pretty ill-formed, and I really want to know if there's a genuine argument against it in any complex application. (My suspicion is that no, there is not, but I'm trying to be generous and curious.)
2 comments

The biggest con is that you have to do all of the legwork of learning how static typing works, and types in TS can be fairly complex.

When you have a team of engineers, this means your entire team needs to either learn or lean on an expert when tougher situations arise.

The thing is, you have to implicitly understand the "types" of javascript objects anyway, otherwise you can't use them.

All the type system does is make that implicit knowledge explicit, and a long the way, stops you from doing things that are likely to cause issues.

Yes, but properly typing your JS objects can still be quite hard
Less charitably, it means you need a competent team?
Competent in types, yes. Just like you’d want a team competent in functional programming before starting a project in Haskell.

It would be unfair to consider your team incompetent just because they are experts with another set of tools. It’s also unreasonable to expect these things to be quickly learned (TypeScript types are not friendly). But I think it’s reasonable to explain the benefits of this approach and to help your ramp up and learn the skill.

But, anyway, I understand the frustration. I’m usually the one trying to get my team to understand the value of modeling problems in type systems.

If complex situations arise, they can slap `any` on it, at least it would be explicit, and marker to revisit in the future.

Is there really that much legwork otherwise? Adding ": string" to a function parameter assumes they know what a string is (which should already be the case), adding an object type assumes knowing what an object is, etc.

There is a big difference between typing your application (e.g. changing (arg) => {} to (arg: string): void => {}) and modeling your application in the type system.

Simply adding types is usually not too difficult and it is still quite beneficial. It does eliminate certain kinds of bugs.

Modeling your application in a type system means making invalid states unrepresentable and being as precise as possible. This is a lot more work, but again is eliminates more kinds of bugs that can occur.

An example of this being complex: earlier this week I wrote a generic React component that allows users to define which columns of a table are sortable. I wanted to prevent any invalid configurations from being passed in. This is what it looks like: https://tinyurl.com/bdh6xbp6

It's a bit complex but the compiler can guarantee that you're using the component correctly. This is more important and useful when it comes to business logic.

Yes, but, I'd argue it's trading one type of endless, tedious work for a different type of concrete, meaningful work.
I agree! It’s still not an easy sell though.
I'm not trained as a programmer/software engineer, but this was ChatGPT's response:

1. Added Boilerplate and Ceremony: Simple tasks may require extra type declarations and structures, adding “ceremony” that feels unnecessary for quick one-off solutions.

2. Rigid Type Constraints: Combining different data types or working with unclear data shapes can force complex type solutions, even for simple logic, due to strict compilation rules.

3. Complex Type Definitions for Simple Data: Handling semi-structured data (like JSON) requires elaborate type definitions and parsing, where dynamically typed languages let you manipulate data directly.

4. Refactoring Overhead: Small changes in data types can cause widespread refactoring, turning minor edits into larger efforts compared to flexible, dynamically typed environments.

5. Complexity of Advanced Type Systems: Powerful type features can overwhelm trivial tasks, making a few lines of code in a dynamic language balloon into complex type arguments and compiler hints.

All of those come down to "Let the compiler guess about my data, and it may produce correct results in some of the cases."

A risk is, unexpected data (empty field instead of zero; a real number introduced in untested corner cases where only an integer will actually work etc) can cause issues after deployment.

Those 'complex' requirements mean, if you want a reliably correct program well then you'll have to put in this much work. But go ahead, that 'trivial task' may become something less trivial when your task fails during Christmas sales season or whatever.