You can define primitive type aliases (e.g. string identifiers) in TypeScript that prevent you from using the wrong type using unique symbols:
type userId = string & {readonly id: unique symbol};
type projectId = string & {readonly id: unique symbol};
// A string can't just be assigned as a userId anymore, but this works.
const myUserId: userId = "u001" as userId;
// TS2322: Type 'userId' is not assignable to type 'projectId'. ๐
const myProjectId: projectId = myUserId;
type projectId = string & {readonly id: unique symbol};
// A string can't just be assigned as a userId anymore, but this works.
const myUserId: userId = "u001" as userId;
// TS2322: Type 'userId' is not assignable to type 'projectId'. ๐
const myProjectId: projectId = myUserId;