Hacker News new | ask | show | jobs
by 01ce8c91872dd6d 1232 days ago
and my reply to you would be showing you virtually any TS codebase I ever saw.

strict typing is great, but the rest of TS features are just trying to put Java into Javascript, empowering people to turn 100 LOC worth of functionality into 1000 LOC of cruft

4 comments

> strict typing is great, but the rest of TS features are just trying to put Java into Javascript

There are no other features of TS that aren't static typing. It is only static typing. (OK, I suppose you could make an argument for enums, but it's still 99%.)

Are you serious right now???

Like... Half the original point of TS was to add features to JS that weren't there originally.

Granted, as the base language evolved the gap has become smaller, but it's still there.

Interfaces being one such example.

There's also things you can do in JS that TS will bitch about. For example, try using object destructuring in a class constructor to create optional named parameters for a class.

Works perfectly in Vanilla JS, but TS will throw a hissy-fit.

>> Try using object destructuring in a class constructor to create optional named parameters for a class. Works perfectly in Vanilla JS, but TS will throw a hissy-fit.

What?

You mean like this?

    class Foo {
        constructor({opt1, opt2, opt3}: {opt1: string, opt2?: number, opt3?: Object}) {
    
        }
    }
https://www.typescriptlang.org/play?#code/MYGwhgzhAEBiD29oG8...
The only new runtime feature that Typescript brings to Javascript is enums.* Everything else is just types. Interfaces, for example, are just a way of defining a shape that data will fit to. They are (almost) equivalent to the `type MyType = { key1: string /* etc */ }` construct, and behave more like an ML record type than a Java interface.

Also, I don't know what exactly you're describing, but objects as optional named parameters are a common technique in Javascript and therefore very well sorted in Typescript. I'm on my phone so this might not work brilliantly, but something like this:

    // This could also be an interface... ;)
    type Params = {
        // These keys are optional
        // (Note the question mark)
        height?: number | string
        width?: number | string
    }
    
    class Rectangle {
        constructor({height, width}: Params = {}) {
            console.log(height, width);
        }
    }
I've not checked that, but it should type check fine. We need to tell Typescript that the param keys can be optional, I used the question mark here, but if you've already got a type, you can use the Partial<T> type to cover it to having all optional keys. We also need to see a default value if the object isn't passed, but that's true in Javascript as well (otherwise we'd get a runtime exception that you can't destructure undefined).

I can definitely empathise with the idea that some Typescript developers just use it as an opportunity to write Javascript-flavoured Java, but this is mostly a stylistic choice (and completely possible in raw Javascript too). But Typescript is very explicitly designed you match the usage patterns of Javascript directly - i.e. if your Javascript code runs (and makes sense), you should be able to write an identical version in Typescript and have it be accepted by the type checker. Obviously that's never going to be entirely the case, but I really find I have many issues porting idiomatic Javascript too Typescript - and where I do, it's usually because the Javascript was wrong in the first place.

* That's not actually entirely true, I forgot about field declarations in constructors, but I don't think I've ever seen that used in the wild outside of very old Angular codebases.

I like enum and use field declarations as much as possible. But I use classes as value types so my goal is to make them as concise as an equivalent function if possible. The fact that they’re classes is just an implementation detail primarily for performance purposes.

There are a few others, mostly discouraged these days (namespace and module runtime keywords come to mind). Mostly they’ve treated these as legacy mistakes (good!), but they introduced a new one recently that baffles me given that posture: `accessor` as a shorthand for getter/setter pairs, with no clear authoring benefit for working with the underlying private value.

In that case, why not just create an object? With a constructor function, that could look something like

    (name: string, age: number) => ({ name, age: age * 2 })
Or even just without the constructor, if the data is so simple:

    { name: "Bill", age: 62 }
I'd have thought that would be the quickest option, because then you're not messing around with prototypes at all.

Also, what do you mean by the accessor shorthand? I don't know what you mean off the top of my head, and searching for it has just brought me back to this post!

Using a class has some JIT optimization benefits if you always construct a value of the same shape.

Accessors: https://devblogs.microsoft.com/typescript/announcing-typescr...

Both examples you gave are type related. Obviously typescript will stop you from making type errors. That’s the whole point.

> Half the original point of TS was to add features to JS that weren't there originally

That’s simply not true. The TS website says “typescript becomes JavaScript via the delete key” along with many other statements that directly contradict this.

> Are you serious right now???

He (or she) is totally serious and I agree.

Here is what I wrote here in some discussion a few days ago: https://news.ycombinator.com/item?id=34454774

-----

TypeScript isn't another language though. It is the latest official ECMAScript plus type annotations. Only some very, very few, rare, old stuff like enums really is different code. 99% of TypeScript is just "remove the types to get ECMAScript".

That TypeScript, the tool,also adds a transpiler is a distraction that made a lot of people believe TS is a different language. But the TS folks have always taken great pain to only ever support features that are or are about to be in the ECMAScript standard, and not to deviate from it. That they did initially with some namespace stuff and enums was before ES2015, when JS was lacking some things many people thought were essential. Even then they only added less than a handful of "TypeScript-code".

When you look at the Babel "transpiler" for Typescript, before they added a bit more for class stuff, it pretty much showed that "transpilation" of TS to JS - as long as you targeted a recent ES version - was achieved by doing nothing more than to remove all those type annotations.

I'm still mad at the TS guiys for muddying the waters so much by confusing soooo many people by bundling type checking and transpilation in one tool. This could have been much more clear. I too stuck to using Flow for quite some time until I realized TypeScript really is Javascript, while Flow communicated in its architecture and usage already that it just "added types" (literally).

------

Actually changing the nature of Javascript, and quite radically too, were those who wrote the newer spec themselves - introducing more and more "class" things.

> Interfaces being one such example.

They are not part of the JS code produced, they are simply type annotations. They don't change the actual JS code at all.

Being fine with JSDoc but not with TS types is strange to me, there is no difference as far as the JS code outcome is concerned unless you - needlessly! - use the very few, mostly legacy (made obsolete by ES2015+), things in TS that actually end up as JS.

Just treat the TS types exactly the same as the JSDoc: It's just comments, it's not part of the code! Get it removed by Babel or tsc just like you could remove (as packers will do) the JSDoc comments for a production build.

I once started with Flow (the other JS type checker), experimented with JSDoc+Webstorm as praised here, and very quickly found an actual type checker and full type annotations are far superior.

Maintenance and team work, especially when people change what projects they are working on, and even more when you have (your own) libraries that other teams use to build something atop of, then string types are a godsend IMO. And why would I go for the far inferior JSDoc "solution"?

I too am VERY keen on using ECMAScript. If TypeScript really messed with the underlying code I would not have chosen it. I simply avoid enums and the other stuff is not even on the radar any more, nobody needs to use the namespacing hacks any more that TS once introduced because prior to ES2015 JS was severely lacking.

Have fun doing extra work:

- writing unit tests that will likely be not exhaustive

- refactoring your unit tests constantly each time you change something

- do all that without the assistance of a compiler telling you what broke

- having to read code to infer types by hand

All all of that for what? so that your code still breaks.

Comparing strings by hand is certainly the best use of human time. If we only had machines capable of doing that.

> My velocity is so high! Look at all those "type mismatch" Jira tickets I've closed in the last month! I am a 10xer. I've multiplied my work 10x!

- Average TypeScript hater testimonial

I hate TS, I use proper OOP style JS with JSDOC and Webstorm type-hints.

Never have any of the issues you mention and even better, never have to deal with the fucking Typescript compiler...

>> the rest of TS features are just trying to put Java into Javascript, empowering people to turn 100 LOC worth of functionality into 1000 LOC of cruft

Not sure what features those are, but TypeScript still has first-class functions, higher-order functions, and algebraic data types. Those are all excellent tools for not writing Java. If people are writing Java code in TypeScript, they're missing out on all the features and power available to them that aren't in Java.

> trying to put Java into Javascript,

Our current project has Java in the backend written in Java and Java in the frontend written in Typescript. So many layers of abstractions for submitting forms.