Skip to content

Instantly share code, notes, and snippets.

@Reshetnyak
Last active February 5, 2020 09:38
Show Gist options
  • Save Reshetnyak/f2f4fce92e061486a2b231fd57ba5c78 to your computer and use it in GitHub Desktop.
Save Reshetnyak/f2f4fce92e061486a2b231fd57ba5c78 to your computer and use it in GitHub Desktop.
Type guard helpers
/**
* @type T {Object} expected type of provided object
* @param obj {Object} object
* @param prop {string} key of an object which indicates expected type
* @returns {boolean} provided object is type T
*
* @example
* interface Base {
* name: string;
* age: number;
* }
*
* interface ChildA extends Base {
* occupation: string;
* }
*
* interface ChildB extends Base {
* id: number;
* }
*
* function noop(arg: ChildA | ChildB): void {
* if (is<ChildA>(arg, 'occupation')) {
* // arg is narrowed to ChildA
* arg.name;
* } else {
* // arg is narrowed to ChildB
* arg.age;
* }
* }
*/
function is<T extends object>(obj: object, prop: string): obj is T {
// Original `hasOwnProperty` is used to avoid collisions
return Object.prototype.hasOwnProperty.call(obj, prop);
}
// TODO: add JSDocs
function is<
T extends K,
K extends object = object
>(obj: K, prop: keyof T): obj is T
function is<
T extends K,
K extends object = object
>(obj: K, comparator: (obj: K) => obj is T): obj is T
function is<
T extends K,
K extends object = object
>(obj: K, propOrComparator: keyof T | Function): obj is T {
if (typeof propOrComparator === 'string') {
return Object.prototype.hasOwnProperty.call(obj, propOrComparator);
} else if (typeof propOrComparator === 'function') {
return propOrComparator(obj)
}
throw new Error('Second argument should be either key of the object or comparator function');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment