Hacker News new | past | comments | ask | show | jobs | submit login

I'm aware of some of those, but I think they're all suboptimal compared to actual nominal types.

In particular iirc you can't use your nominal/branded type as a map key in a type-safe way.




Not sure what you mean:

    enum A {}

    type B = { a: number } & A;

    function newB(i:number) {
      return { a: i } as B;
    }

    let b:B = newB(5);

    let m:Map<B, string> = new Map();

    m.set(b, "test");
    m.set({ a: 2 }, "test"); // errors


What he means is that you didn't _used_ to be able to do this:

    declare const NOMINAL_BRAND: unique symbol;
    enum UserIdType {}
    type UserId = string & {[NOMINAL_BRAND]: UserIdType}
    type UserMap<V> = { [key: UserId]: V };
But at some point in the past few years, this is now supported and things like this work as expected:

    const userId: UserId = "234" as UserId
    const coolUsers: UserMap<boolean> = {}
    coolUsers[userId] = true // works
    coolUsers["isThisOkay"] = false // fails


Interesting, I thought that wasn't possible, but now I feel like I'm just confused and mixing it up with something else that wasn't possible but can't remember well enough.

But anyway, what I want from TS is

    type UserId = unique string; // or something
    const userId = "1234" as UserId
and no further boilerplate or trickery to get it to work. Would certainly be nice.


You can get close to that:

https://github.com/seancroach/ts-opaque




Consider applying for YC's Spring batch! Applications are open till Feb 11.

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

Search: