3 ms·
I've used the approach described for uuids on a project and I liked it. We were using typescript so we went further using template literal types [1] type U
by stillpointlab 1y ago
I've used the approach described for uuids on a project and I liked it. We were using typescript so we went further using template literal types [1]
type UserId = `user:${uuid}`;
type OrgId = `org:${uuid}`;
This had the benefit that we could add validation (basic begins with kind of logic) and it was obvious upon visual inspection (e.g. in logs/debugging).
1. https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html https://www.typescriptlang.org/docs/handbook/2/template-lite...
- oehpr 1y agoI assume you used these against a relational database? Did you commit those ids with the prefix still attached? or did you `.split()[1]` or something? I think it's a pretty good idea. I'm just wondering how this translated to other systems.
- stillpointlab 1y agoWe were using Mongo and stored the ids with the prefix in the DB as the primary key. Pretty much everywhere we were passing them around as strings, never as 128 bit int, so there was no integrity checking outside of the app layer. The only drawback was marshalling the types when they come out of the db layer. Since the db library types were string we had to hard cast them to the correct types, really my only pain. That isn't such a big deal, but it means some object creation and memory waste, like: // pseudo code: const results = dbclient.getObjectsByFilter( ... ); return results.map(result => ({ id: result.id as ObjectId, ... })); We normally didn't do it, but it would be at that time you could have some `function isObjectId(id:string) : id is ObjectId { id.beginsWith("object:"); }` wrapper for formal verification (and maybe throw exceptions on bad keys). And we were probably doing some type conversions anyway (e.g. `new Date(result.createdAt)`). If we were reading stuff from the client or network, we would often do the verification step with proper error handling.
- spartanatreyu 1y agoTypescript's template literal types are awesome when creating values that have to match a specific format. But depending on the format it can sometimes be tricky to narrow a string back down to that format. We have type guards to do that narrowing. (see: https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates https://www.typescriptlang.org/docs/handbook/2/narrowing.htm..., but their older example is a little easier to read: https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types https://www.typescriptlang.org/docs/handbook/advanced-types....) If writing the check is too tricky, sometimes it can just be easier to track the type of a value with the value (if you can be told the type externally) with tagged unions (AKA: Discriminated unions). See: https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html#discriminated-unions https://www.typescriptlang.org/docs/handbook/typescript-in-5... And if the formats themselves are generated at runtime and you can use the "unique" keyword to make sure different kinds of data are treated as separate (see: https://www.typescriptlang.org/docs/handbook/symbols.html#unique-symbol https://www.typescriptlang.org/docs/handbook/symbols.html#un...). You can combine `unique symbol` with tagged unions and type predicates to make it easier to tell them apart.