Hacker News new | ask | show | jobs
by jinushaun 2493 days ago
Disappointed that the article alluded to but never explains why classes should be avoided in Typescript. (Which I agree, btw)

If you’re used to classes, it’s really tempting to create classes for your models. But in Typescript, which gets compiled down to plain old JavaScript, you spend a lot of your time dealing with JSON and plain old JavaScript objects (POJO). These don’t have methods. These don’t have private members. These don’t have constructors.

You actually don’t need any of that. You just want type safety around your JSON and POJO. That’s why more often than not, you’re going to be using interface.

I’m not saying never use classes. But don’t use classes to define models. Use classes for controllers.

5 comments

This sounds very arbitrary, opinionated, and unconvincing. If a class is a co-location of data and methods performed on it, then how is this class:

  class Foo {

    constructor(value) {
      this.value = value;
    }

    addOne() {
      this.value++;
    }
    
    getValue() {
      return this.value;
    }

  }

  const foo = new Foo(1);
any worse than this POJO:

  const foo = {
    value: 1,
    addOne() {
      this.value++;
    },
    getValue() {
      return this.value;
    }
  }
Besides, what are models and controllers in React codebases, and why is using classes for one of these groups any better than for the other?
I think you missed the part where they said you don't need classes for POJOs and models i.e. things which only contain data and do nothing else. If you want methods that operate against the inner data of an object then totally write classes
It’s just that they started their post by saying that classes in Typescript should be avoided. A message "x should be avoided" is very different from "you don’t need x". Compare the statement "you don’t need redux", which has been incorporated into titles of numerous blog posts, with the statement "redux should be avoided".
I still don't hear a good argument as to why you should't use classes for your model.

I use [serializr](https://github.com/mobxjs/serializr) to convert json to my classes, and afterwards I can have all the deligtful methods I want. :-) I love the code clarity this gives, methods are where they are most logical, instead of on some helper object.

There is also class-transformer[1] and class-validator[2] which also do the same job but integrate a bit better into the whole typescript cosmos.

[1] https://github.com/typestack/class-transformer [2] https://github.com/typestack/class-validator

Method implies use of this, which implies they are probably not first class - such would be functions cannot be passed or returned, as the this reference won’t be bound if called as a function.
There's a historical reason why classes are used a lot for models. It's up to you to decide if this reason applies to your project or organization.

A few years ago there was a dilemma between ES6 and TypeScript. A lot of JS developers chose to stay away from TS in order to follow the ES6 path instead. Then TS harmonized with ES6. But it retained a reputation for being an incompatible alternative to ES6 rather than just JS+type annotations. However, if you write classes, they look just like ES6 classes plus type annotations, allaying concerns.

I see why you're missing an explanation on why classes should be avoided. In fact, your opinion is very similar to mine - I also think that, especially in the context of the FP-influenced React, data should be separated from behaviour - I mean how exactly are you going to preserve immutability using OOP? React just works a lot better when there's no self-mutating objects.

Could you elaborate on why you think that classes should be used when implementing controllers? I tend to think of controller classes as singletons, which kind of contradict using classes in the first place.

Any method that mutates returns a copy, pretty easy to preserve immutability in OOP.
Then what do you do about the old version of the mutated object? There will still be references to it in other parts of your object model, which will now be out of date. I think that the concept of objects preserving identity is central to OOP, which simply contradicts immutability.
Could you give a concrete example?

Why would you somehow pass objects around that are not "final"?

I mean the objects that get pinned here and there are specifically designed to serve as wrappers for some state, hence they encapsulate that state, and thus they are mutable. (For example a DB connection/manager object, a service registry, a cookie/localStorage repository.)

Where the immutability usually helps is with shuffling data around, parallel computing (concurrent access, no need to lock), etc.

"Classes considered harmful"