Programming TypeScript has a section on “Simulating Nominal Types” [1]. You define a type that’s impossible to create naturally, and provide a function that asserts something is of that type.
type CompanyID = string & {readonly brand: unique symbol}
type OrderID = string & {readonly brand: unique symbol}
type UserID = string & {readonly brand: unique symbol}
type ID = CompanyID | OrderID | UserID
function CompanyID(id: string) {
return id as CompanyID
}
...
TypeScript can be very confusing sometimes, and given the learning curve I’d caution someone trying to learn modern JS away from starting out with it. But in even small codebases it’s an amazing improvement in safety, especially for refactoring.
That's not good. A type system should be crystal clear, predictable and reliable.
> and given the learning curve
Types should not be a complex thing with a steep learning curve. If you know Assembler and C it's pretty clear what types are about. Added complexity to your codebase is what you should try to avoid at all times. We have a limited capacity of things we can think of at a time, developers should therefore focus on things that really matter. In my daily work I see highly complex piles of spaghetti in TS that are 'type safe' and easy to refactor..
I don't follow how knowing C and Assembler makes types clear and I'd love it if you could clarify.
Nominal types are really a compile time only thing: if you have two structs (or classes) with the exact same fields, I'd expect them to be stored the same way in memory. And as a result I'd expect any function to work on them just fine, as long as they find semantically valid data at the right offsets.
> That's not good. A type system should be crystal clear, predictable and reliable.
The purpose of TypeScript is to provide static types to JavaScript without just turning it into a compile target. TypeScript type system is only confusing because it's modeling real-life ultimately type-less JavaScript code. It's not it's own language with it's own rules -- it lives and dies as JavaScript.
> Types should not be a complex thing with a steep learning curve.
Types can be as simple or complex as needed. Assembler and C have very simple type systems with very few features and can only model very simple situations. Types in TS don't have to be complicated -- blame JavaScript programmers for their crazy designs.
At runtime, TypeScript is JavaScript, so depending on your perspective either encapsulation is impossible (because you don't have types to defend you) or easy (because you use the patterns that JS has to defend encapsulation at runtime, without types).
You can use private to do it OO/Java style, but you don't need typescript for that: ES6 modules let you encapsulate stuff just fine without any type features.
At compile time? It's very simple–use an interface and provide constructor functions that upcast object instances to the interface. Now, only the interface-defined members i.e. the public members are accessible.
At runtime? You can't, it's JavaScript, everything is public (for now at least).
[1] https://learning.oreilly.com/library/view/programming-typesc...