Add the RepoIdString type (#885)

This modifies `core/repoId` so that `repoIdToString` returns not a
`string`, but an opaque subtype of `string` called `RepoIdString`.

This allows us to store stringified `RepoId`s (which is useful whenever
we want value-not-reference semantics, like for use as a map key)
while still maintaining a type assertion that the strings, in fact,
represent valid `RepoId`s.

Test plan: A unit test verifies that it's a flow error to cast a string
to a `RepoIdString`.
This commit is contained in:
Dandelion Mané 2018-09-21 16:54:20 -07:00 committed by GitHub
parent 838092194b
commit b506d40efd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 10 additions and 1 deletions

View File

@ -10,6 +10,8 @@ export opaque type RepoId: {|
+owner: string,
|};
export opaque type RepoIdString: string = string;
export const githubOwnerPattern = "[A-Za-z0-9-]+";
export const githubRepoPattern = "[A-Za-z0-9-._]+";
@ -33,6 +35,6 @@ export function stringToRepoId(x: string): RepoId {
return makeRepoId(pieces[0], pieces[1]);
}
export function repoIdToString(x: RepoId): string {
export function repoIdToString(x: RepoId): RepoIdString {
return `${x.owner}/${x.name}`;
}

View File

@ -5,6 +5,7 @@ import {
stringToRepoId,
repoIdToString,
type RepoId,
type RepoIdString,
} from "./repoId";
describe("core/repoId", () => {
@ -22,6 +23,12 @@ describe("core/repoId", () => {
const _unused_name: string = repoId.name;
});
});
describe("RepoIdString type", () => {
it("manually constructing a RepoIdString is illegal", () => {
// $ExpectFlowError
const _unused_repoIdString: RepoIdString = "foobar";
});
});
describe("makeRepoId", () => {
it("allows a simple repoId", () => {
makeRepoId("sourcecred", "sourcecred");