Because it's inherently anti-consumer (not something that anyone would voluntarily opt into) and the EU would have their balls in vices instantaneously?
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.
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.
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.
… 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.
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;
}
}
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__.
> 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”.
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.
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.
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
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.
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.
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.
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.
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?
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.