Skip to content

Instantly share code, notes, and snippets.

@safareli
Last active January 14, 2022 14:16
Show Gist options
  • Save safareli/8e480d72f7e2665b6030b9a08fe93f40 to your computer and use it in GitHub Desktop.
Save safareli/8e480d72f7e2665b6030b9a08fe93f40 to your computer and use it in GitHub Desktop.
Composing TypeScript type guards
/**
* Type representing a guard function accepting Input and some other arguments
* while refining type of input as `Output`
*/
export type TypeGuard<
Input,
Output extends Input,
Args extends unknown[] = []
> = (value: Input, ...args: Args) => value is Output;
/**
* Combines multiple TypeGuards using `&&` operator
*/
export function and<I, O extends I, O2 extends O, A extends unknown[] = []>(
f: TypeGuard<I, O, A>,
g: TypeGuard<O, O2, A>
): TypeGuard<I, O2, A> {
return (value: I, ...args: A): value is O2 =>
f(value, ...args) && g(value, ...args);
}
/**
* Combines multiple TypeGuards using `||` operator
*/
export function or<I, O extends I, O2 extends O, A extends unknown[] = []>(
f: TypeGuard<I, O, A>,
g: TypeGuard<I, O2, A>
): TypeGuard<I, O | O2, A> {
return (value: I, ...args: A): value is O | O2 =>
f(value, ...args) || g(value, ...args);
}
@safareli
Copy link
Author

safareli commented Jun 2, 2021

@safareli
Copy link
Author

safareli commented Jun 2, 2021

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment