Skip to content

Instantly share code, notes, and snippets.

@dcolthorp
Created May 1, 2017 14:20
Show Gist options
  • Save dcolthorp/3ee6dd743b9240ed11b9b3701bd59077 to your computer and use it in GitHub Desktop.
Save dcolthorp/3ee6dd743b9240ed11b9b3701bd59077 to your computer and use it in GitHub Desktop.
/** An empty type which "brands" a value as having been checked for validity */
enum IsValidBrand {}
/** A `Valid<T>` is just a T that the type system knows is valid. */
export type Valid<T> = T & IsValidBrand;
/** This is some arbitrary example type which we want to validate. */
interface Model { nonEmptyArray: number[] }
/** A predicate to check that a model is valid. The return type tells TypeScript that this proves the argument is valid. */
export function isValidModel(m: Model): m is Valid<Model> {
return m.nonEmptyArray.length > 0;
}
/** A helper function to attempt validation of a model. */
export function validateModel(m: Model): Valid<Model> | undefined {
if (isValidModel(m)) {
return m;
} else {
return undefined;
}
}
export function needsValidModel(m: Valid<Model>): string {
return m.nonEmptyArray.join(", ")
}
const someModel: Model = { nonEmptyArray: [1]}
// This won't compile, since someModel isn't known to be valid:
//needsValidModel(someModel);
if (isValidModel(someModel)) {
// TypeScript knows this is OK, because isValidModel proves
// that someModel is valid.
needsValidModel(someModel);
}
// This is OK as well.
const validModel: Valid<Model>|undefined = validateModel(someModel);
if (validModel) {
needsValidModel(validModel)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment