automerge / hypermerge

Build p2p collaborative applications without any server infrastructure in Node.js
MIT License
1.28k stars 66 forks source link

Use opaque types for document ids and actor ids #29

Closed jeffpeterson closed 5 years ago

jeffpeterson commented 5 years ago

A number of bugs and frustrations have stemmed from the conflation of actor ids with document ids (and others) in the code-base. This PR is a step towards solving this problem.

In the future, it's possible we'll change the actual string values of these types to be more distinct, but we can start by helping the type-checker do its job.

The PR adds 8 new types:

export type BaseId = string & { id: true }
export type DocId = BaseId & { docId: true }
export type ActorId = BaseId & { actorId: true }
export type HyperfileId = BaseId & { hyperfileId: true }
export type DiscoveryId = BaseId & { discoveryId: true }

export type BaseUrl = string & { url: true }
export type DocUrl = BaseUrl & { docUrl: true }
export type HyperfileUrl = BaseUrl & { hyperfileUrl: true }

The values represented by these types are still strings, but the type-checker sees them as a unique (unconstructable) sub-type of string: DocUrl can be used as a string, but not vice versa.

All of the internal and external functions have been updated to use these types. In particular, if you're using TypeScript, the Repo and Handle methods (e.g. repo.open(url: DocUrl)) will no longer type-check if plain strings are passed in. Instead, use the result of repo.create(): DocUrl as the url or typecast the url: repo.open(urlString as DocUrl).