Created
May 1, 2017 14:20
-
-
Save dcolthorp/3ee6dd743b9240ed11b9b3701bd59077 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** 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