Hacker News new | past | comments | ask | show | jobs | submit | thepaulmcbride's comments login

Anyone know why this is only available in the US?


Because it's inherently anti-consumer (not something that anyone would voluntarily opt into) and the EU would have their balls in vices instantaneously?


If you had a lifetime subscription of around $250, I’d buy it instantly.


Anytime I’ve come across the need to do this, I’ve found a class is a better and less complicated solution.

I really like the pattern of value objects from Domain Driven Design. Create a class that stores the value, for example email address.

In the class constructor, take a string and validate it. Then anywhere that you need a valid email address, have it accept an instance of the Email class.

As far as I understand classes are the only real way to get nominal typing in TypeScript.


Classes can also make use of the native `instanceof` JavaScript operator [0].

It is also possible to then infer a type from a class so you can use both the class where you want to discriminate types and the type where you really only care about the shape.

The absolutism towards OOP/FP -- instead of embracing the right use cases for each -- always ruffles me in the wrong way. C#, for example, does a great job of blending both OOP and FP (borrowing heavily from F# over the years). JS and by extension TS has the same flexibility to use the right paradigm for the right use cases, but it seems that everyone wants to be on one end of the spectrum or the other instead of accepting that JS is an amalgamation.

Evan You had a great quote on this where he correctly calls out much of the complexity and performance issues with React as being rooted in pushing against the language rather than embracing it.

[0] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...


Classes are very underutilised in TypeScript. I recently introduced them to our codebase at my day job and got a fair bit of pushback because it wasn’t “JavaScripty” enough.


That's a weird objection, because Typescript classes are literally Javascript classes[1].

[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...


There was plenty of outrage when classes were added to JS. “JS uses prototypal inheritance, not OOP!”


I'm still a bit cranky about that, but because objects should be good enough for anyone. They aren't even really classes anyway.


If it walks like a duck, and quacks like a duck, for all intents and purposes, it is a duck.


I like classes well enough; I just find that often they over-complicate simple code, especially when you introduce inheritance. Since classes are effectively just syntax sugar I often find it's more intuitive to go with object syntax but to each their own. So long functionality is isolated in modules I'm happy.


> The absolutism towards OOP/FP

… also doesn’t need to proscribe use or non-use of classes. People were doing OOP in JS long before classes were added to the language. I routinely use classes in a FP style because they’re excellent for modeling value types with a stable structure.


JS classes are a great fit for FP. They're just functions with closures and a little syntactic sugar.


Given a Branded / Nominal interface, they look about the same usage wise but the branded type disappears at runtime (whether that is a benefit or a detriment depends on your use case):

    type Email = Branded<string, 'email'>

    function Email(maybeEmail: string): Email {
      assertIsEmail(maybeEmail);
      return maybeEmail;
    }

    function assertIsEmail(value: string): asserts value is Email {
      if(!isEmail(value)) throw TypeError("Not an email");
      return value;
    }

    function isEmail(value: string): value is Email {
      return value.contains("@");
    }
Versus:

    class Email {
      #email: string;
      public constructor(maybeEmail: string) {
        if(!isEmail(maybeEmail)) throw TypeError("Not an email");
        this.#email = maybeEmail;
      }
      valueOf() {
        return this.#email;
      }
    }


> As far as I understand classes are the only real way to get nominal typing in TypeScript.

Although classes and instances are ultimately structural, right?

    let foo = new Foo();
    assert(foo.constructor == Foo);


foo.constructor actually doesn’t matter; foo.__proto__ == Foo.prototype is the one that actually makes things chug, and you can change the class of a value by changing its __proto__.


Yep, you’re absolutely right


> Anytime I’ve come across the need to do this, I’ve found a class is a better and less complicated solution ... As far as I understand classes are the only real way to get nominal typing in TypeScript.

How are classes going to help? As far as I understand TS is structural period. Ex this is valid (!):

  class Email {
      constructor(public email: String) {}
  }
  let x: Email = new Email('foo@foo.com')
  let y = { email: '73'}
  x = y;


I had the same initial reaction, but it turns out that if you have at least one private member, even with the same signature, it works as the parent comment suggests.

For example, these two classes are distinct to TypeScript:

    class Name {
        constructor(private value: string) {}

        getValue() {
            return this.value;
        }
    }

    class Email {
        constructor(private value: string) {}

        getValue() {
            return this.value;
        }
    }

    const email: Email = new Name(“Tim”); // Error: (paraphrasing) conflicting private declaration of “value”.


You’re right. This is what I meant, but I was not at all clear in my original comment.


I believe what the OP meant by "to get nominal typing in TypeScript" is that the type information is available at runtime through the use of the `instanceof` keyword.

I am surprised your code doesn't give an error, x and y are definitely not the same thing because `x instanceof Email` would be false at the end of that code. But like you said, to TS x and y are indeed the same type because they have the same structure. In practice both can be used interchangeably in the code (even if Email extended another class) with the sole exception of the `instanceof` keyword.


Yeah, classes are generally better than branded types for objects (unless you're just building discriminated unions).

What's particularly better these days is that you get nominal typing and brand checks with standard private fields:

    class Foo {
      #brand;

      static isFoo(o): o is Foo {
        return #brand in o;
      }
    }


I don’t quite see why you’d need to brand simple objects at all! Just give them meaningful field names.

Branding primitives is useful because you don’t otherwise have a name that you can control (e.g. feet versus meters as was suggested elsewhere in this thread, both of which would have type “number”).

The article starts with the example of two different object types with field “x: number”. In that situation you should be branding the field, not the object! If the field has the same name and the same branded type, structural typing is correct for that object shape.


Is this different/better than using `instanceof`?


This is really neat, thank you for sharing!


Just got the email from them explaining the changes. It goes like this.

Vercel: We’re changing our pricing. Our community has told us we’re expensive. Also Vercel: Your bill is going up.


For a small subset of customers (~8%), these pricing changes are projected to increase bills — most of them $5 or less. For all customers with projected increases, new metrics will be free for the first 3 months. Happy to work with you on optimizing your usage further: lee at vercel dot com.


Question on the free Hobby plan: I'm assuming these included amounts are per month? Or per account? The documentation isn't explicit. https://vercel.com/docs/accounts/plans/hobby


Yep, per month. Thank you, we will update this.


Same thing here. Would be great if the email gives an idea of what the estimated cost will be from each service. Guess we will just have to wait for the first bill.


Mine is set to triple.

They’re giving us a 3 month grace period, but unfortunately don’t offer a breakdown of what is causing the increase.


Before these changes go live (and before the grace period begins) you'll be able to see your current pricing vs. new pricing in the dashboard, so you can optimize from there.


What parts of your bill are going up?


Same ahahah


While Google makes money showing these ads to us, I don’t expect these changes will be for our benefit.


They have to. I mean, google wants to sell ads. If the service (google search) was crap, less people would use it. Kind of like bing or the other search engines that barely anyone uses outside of a few tech circles.

It’s not perfect but google search is still pretty good if you compare it to other search engines engines and the god awful search functionality of pretty much any site. Even big sites like amazon or reddit are terrible.


Would you consider someone without Go experience if they’ve got equivalent experience in Node? I’m very keen to learn Go, but haven’t used it professionally.


This reminds me a lot of value objects from Domain Driven Design


If you appreciate the patterns from DDD and the idea of domain modeling with type systems, I highly recommend checking out "Domain Modeling Made Functional" by Scott Wlaschin.


I recently watched a talk he gave with the same title. It was excellent. Honestly having one of those planning/discovery meetings before any code gets written can prevent so many nasty problems.


The regional popup on that website blocked me from seeing the page. What an extremely hostile bit of UX!


Do we just call everything that misbehaves “extremely hostile” now? Would be keen to see how this relates to any sensible definition of hostility.


I just selected USA and it hid the popup and allowed me to view it!


I didn't get any regional popup. What does it say?


That there are no retailers in your country and you need to choose another one. I removed it with uBlock's popup removal tool.

https://i.imgur.com/4d0OkDv.png


Offers you a choice of links to retailers in your country. Blocks interaction and covers up centre of page, although scrolling is still possible.


yup, very annoying. Open devtools and delete the element and the page functions fine.


After almost 5 years of operation, WeCode NI has started to fail and I don't have the time required to keep it running. So I've decided to shut it down and make the code public.


> There are lots of things I would do differently if I were to start this project again, so please don't take this as an example of best practice. I have learned a lot since building this project and I would do things differently now.

When should we expect an article of yours about what you would have done it differently?


Yes, I actually published that shortly after this post. https://paulmcbride.com/posts/sunsetting-wecode-ni


Offt, not a good look for Railway, Render or Vercel!


They all need to make margins on top of aws/gcp expenses. Its just a knock on effect from such expensive public cloud egress.


I’m a fan of all three, but my mindset is that I’m not just paying for raw infrastructure, I’m paying for the engineering work I don’t have to do when I use them.


I’m a fan of them too. Their pricing gives me a “we will punish your success” vibe. I suppose that’s preferable to paying through the nose for not scaling.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: